home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / macros / latex209 / contrib / textyl / src / textyl.c < prev    next >
C/C++ Source or Header  |  1993-11-07  |  80KB  |  3,423 lines

  1. /* Output from p2c, the Pascal-to-C translator */
  2. /* From input file "textyl.p" */
  3.  
  4. #include    "defs.h"
  5. #include    "globals.h"
  6. #include    "tables.h"
  7.  
  8. extern int    abs PP((int));
  9.  
  10. /*----------------------------------------------------------
  11.         TeXtyl  line-drawing interface for TeX.
  12.               copyright (c) 1987 John S. Renner
  13.                 All rights reserved.
  14.  
  15. ABSTRACT: TeXtyl reads in a DVI file, and processes 'specials'
  16.         that refer to graphics capabilities that it knows about,
  17.         like line, spline, ThickThinSpline, and musical
  18.         beams and slurs. TeXtyl then outputs a new DVI file,
  19.         with the special-macros expanded and converted to
  20.         DVI-commands for character setting.
  21.  
  22. DEPENDENCIES:  Few assumptions about Pascal are assumed. All
  23.         identifiers are unique to eight characters. There are
  24.         notes to indicate system-dependencies.
  25.         I assume the standard definition of "READ(fil, x)" to be
  26.         equivalent to "x := fil^; GET(fil)" , and
  27.         "WRITE(fil, x)" == "fil^ := x; PUT(fil)" .
  28.         Arrays are passed by reference (VAR) for efficiency.
  29.         See also the "sysdependent"  procedure;
  30.         Problem areas, or areas for expansion are marked with ###
  31.  
  32. -------------------------------------------------------------*/
  33. /*-Revision History:
  34.     Jun. 1986  v1.0   Basic version of TeXtyl
  35.     Dec. 1986  v1.1   Added adaptive subdivision for spline
  36.                         interpolation. Added Cardinal basis.
  37.     Mar. 1987  v1.2   Added F and W flags for beginfigure
  38.                         to allow required and/or actual dimensions
  39.                         to interface with files output by the
  40.                         DP drawing program from Carnegie-Mellon
  41.                         also various fixes
  42.     Apr. 1987  v1.3   Added linestyles (dotted, dashed, dotdashed)
  43.     Aug. 1991         Translated to C with p2c, then hacked a bit. (Ken Yap)
  44. */
  45.  
  46. /* ===========================TYPES============================= */
  47.  
  48. /* ---- PUBLIC types ---- */
  49.  
  50. typedef int     MusIndex;
  51. typedef int     SplineSegments[MAXSPLINESEGS][2];
  52.  
  53. /* ----- Private Types ---- */
  54.  
  55. typedef struct FontInfRec
  56. {
  57.     int32           Cht, Cdp, Cwd;
  58.     double          Angle;
  59. }               FontInfRec;
  60.  
  61. /* vector font info */
  62.  
  63. typedef struct VectFontInfRec
  64. {
  65.     VectKind        vkind;
  66.     int32           DesSize, PenSize;
  67.     VThickness      psize;
  68.     int32           MaxVectLen;
  69.     charstring      FontName;
  70.     int32           Cksum;
  71.     int        Isdefined;
  72.     int32           DVIFontNum;
  73.     FontInfRec      FontInfo[128];
  74. }               VectFontInfRec;
  75.  
  76. /* music font info */
  77.  
  78. typedef struct MusFontInfRec
  79. {
  80.     int32           DesSize, Family;
  81.     charstring      FontName;
  82.     int32           Cksum;
  83.     int        Isdefined;
  84.     int32           DVIFontNum, Staffsize, ghu, gvu;
  85.     FontInfRec      FontInfo[128];
  86. }               MusFontInfRec;
  87.  
  88. /*
  89.  * representation of list of fonts that have to be defined
  90.  * before we output the BOP of the page we just scanned
  91.  */
  92.  
  93. typedef struct ToBeDefinedRec
  94. {
  95.     char            which;
  96.     int32           indx;
  97. }               ToBeDefinedRec;
  98.  
  99. /* ==============================VARS============================ */
  100.  
  101. /* ----- Private vars */
  102. static int32    ourxpos;    /* internal x-position on page */
  103. static int32    ourypos;    /* internal y-position on page */
  104.  
  105. static VectFontInfRec *VFontTable[SizVFontTable];
  106. static MusFontInfRec *MFontTable[SizMFontTable];
  107. /* the font tables, and the number of fonts defined in each */
  108. static int32    VFontsDefd, MFontsDefd, LFontsDefd;
  109.  
  110. static int    GDVIFN = 301;    /* dvi font number currently in use */
  111.  
  112. /* table of fonts yet  To-Be-Defined */
  113. static ToBeDefinedRec TBD[MAXTBDs];
  114. static int32    FTBDs;        /* number of fonts to be defined for current page */
  115.  
  116. static Item    *pageitems;
  117. /*
  118.  * list of primitives in current use in the current figure on the current page
  119.  */
  120.  
  121. static int32    specstart = 0;
  122. /*
  123.  * the place in the DVI buffer where the start of the special begins.
  124.  * this is so that we know how far to back up and over-write
  125.  * the old \special macro string with the cmds of our 'macro-expansion'
  126.  */
  127.  
  128. static int32    multifigure;    /* depth of definition recursion of figures */
  129. static int    skiptsclamp;    /* DEBUG: should we skip post-clamping ties */
  130. static int    ErrorOccurred;    /* global flag in case some error happened */
  131.  
  132.  
  133. /* ----- End private vars */
  134.  
  135. static short    tfm[TFMSIZE + 101];
  136.  
  137. static char     s = 0;
  138. struct stackrec
  139. {
  140.     int32           sh, sv, sw, sx, sy, sz;
  141. }               stack[STACKSIZE + 1];
  142.  
  143. static int32    inwidth[256];
  144. static int32    tfmchecksum;
  145. static double   conv, trueconv;
  146. static int32    numerator, denominator;
  147. static double   mag, magfactor;
  148. static int32    maxv, maxh, maxs, maxpages = 10000, totalpages;
  149. static double   resolution = 300.0;
  150. static int    inpostamble;
  151. static int32    newbackptr = -1, oldbackptr = -1, p, k;
  152.  
  153. /* forward declarations */
  154. static void definebeams PP((MusFontInfRec ** M));
  155. static void definevectors PP((VectFontInfRec ** Vec));
  156.  
  157. static jmp_buf  _JL666;
  158.  
  159. static int 
  160. opentfmfile(tfmname)
  161.     charstring      tfmname;
  162. {
  163.     charstring      thefilename;
  164.     char           *path, *p, *q, *getenv PP((char *));
  165.  
  166.     if ((path = getenv("TEXFONTS")) == 0)
  167.         path = DEFTEXFONTS;
  168.     if (tfmfile != NULL)
  169.     {
  170.         fclose(tfmfile);
  171.         tfmfile = NULL;
  172.     }
  173.     for (p = path; p != 0 && tfmfile == NULL; p = q ? q + 1 : 0)
  174.     {
  175.         if ((q = strchr(p, ':')) == 0)
  176.             strcpy(thefilename, p);
  177.         else
  178.             strncpy(thefilename, p, q - p);
  179.         strcat(thefilename, "/");
  180.         if (strcmp(thefilename, "./") == 0)
  181.             thefilename[0] = '\0';
  182.         strcat(thefilename, tfmname);
  183.         tfmfile = fopen(thefilename, "r");
  184.     }
  185.     return (tfmfile != NULL);
  186. }
  187.  
  188. void 
  189. jumpout()
  190. {
  191.     longjmp(_JL666, 1);    /* global label */
  192. }
  193.  
  194. void 
  195. complain(severity)
  196.     int             severity;
  197. {
  198.     fprintf(logfile, "Error in fig#%ld on page %ld\n", pgfigurenum, currpagenum);
  199.     switch (severity)
  200.     {
  201.     case ERRNOTBAD:
  202.         putc(ERRSIGNAL, logfile);
  203.         break;
  204.     case ERRBAD:
  205.         putc(ERRSIGNAL, logfile);
  206.         ErrorOccurred = true;
  207.         break;
  208.     case ERRREALBAD:
  209.         fprintf(logfile, "%c! ", ERRSIGNAL);
  210.         ErrorOccurred = true;
  211.         break;
  212.     }
  213. }
  214.  
  215. double 
  216. float_(i)
  217.     int32           i;
  218. {
  219.     return ((double) i);
  220. }
  221.  
  222. static int 
  223. tolowercase(let)
  224.     int             let;
  225. {
  226.     return (isupper(let) ? tolower(let) : let);
  227. }
  228.  
  229. #define    streq(a,b,n)    (!strncmp((a),(b),(n)))
  230.  
  231. /*
  232.  * Move the current DVI position to posx, posy by moving relatively from our current position and store the new position
  233.  */
  234. void 
  235. isetpos(posx, posy)
  236.     int             posx, posy;
  237. {
  238.     ScaledPts       dy, dx;
  239.     int32           numbytes;
  240.  
  241.     dx = posx - ourxpos;
  242.     dy = posy - ourypos;
  243.     numbytes = 1;
  244.     if (dx < 128 && dx >= -128)
  245.         numbytes = 1;
  246.     else if (dx < 32768 && dx >= -32768)
  247.         numbytes = 2;
  248.     else if (dx < TWO23 && dx >= -TWO23)
  249.         numbytes = 3;
  250.     else if (dx < TWO31 && dx >= -TWO31)
  251.         numbytes = 4;
  252.     else
  253.     {
  254.         complain(ERRREALBAD);
  255.         fprintf(logfile, "Panic: dx is too big/small in isetpos: %12ld\n", dx);
  256.     }
  257.  
  258.     cmd1byte(RIGHTLEFT + numbytes - 1);
  259.     /* number of bytes in its arg list */
  260.     cmdSigned(dx, numbytes);
  261.  
  262.     numbytes = 1;
  263.     if (dy < 128 && dy >= -128)
  264.         numbytes = 1;
  265.     else if (dy < 32768 && dy >= -32768)
  266.         numbytes = 2;
  267.     else if (dy < TWO23 && dy >= -TWO23)
  268.         numbytes = 3;
  269.     else if (dy < TWO31 && dy >= -TWO31)
  270.         numbytes = 4;
  271.     else
  272.     {
  273.         complain(ERRREALBAD);
  274.         fprintf(logfile, "Panic: dy is too big/small in isetpos: %12ld\n", dy);
  275.     }
  276.     cmd1byte(DOWNUP + numbytes - 1);
  277.     cmdSigned(dy, numbytes);
  278.     ourxpos = posx;
  279.     ourypos = posy;
  280. }
  281.  
  282. /* put out a character */
  283. static void 
  284. iputchar(charno)
  285.     int             charno;
  286. {
  287.     cmd1byte(PUT1);
  288.     cmd1byte(charno);
  289. }
  290.  
  291. /*
  292.  * set the font number, but only if it is different than the last one
  293.  * we accessed.
  294.  */
  295. void 
  296. isetfont(DVINum)
  297.     int             DVINum;
  298. {
  299.     if (ourfontnum == DVINum)
  300.         return;
  301.     cmd1byte(USEFONT);
  302.     cmd2byte(DVINum);
  303.     ourfontnum = DVINum;
  304. }
  305.  
  306. /* Assumes that the correct font is currently set */
  307. static void 
  308. Tyldot(dotx, doty)
  309.     int32           dotx, doty;
  310. {
  311.     if (dotx != 0 && doty != 0)
  312.         isetpos(dotx, doty);
  313.     iputchar(DOTCHAR);
  314. }
  315.  
  316. /*
  317.  * ### Note: "pageitems" could be extended to be a list
  318.  * { of macrodefinitions which contain primitives , and { then could be
  319.  * instanced.  E.g., a library of common { figures callable from \special level
  320.  */
  321.  
  322. void 
  323. pushItem(depth, newthing)
  324.     int             depth;
  325.     Item           *newthing;
  326. {
  327.     Item           *i, *p;
  328.  
  329.     if (pageitems == NULL)
  330.     {
  331.         if (newthing->kind == Afigure)
  332.         {
  333.             pageitems = newthing;
  334.             return;
  335.         }
  336.         pageitems = NewItem(Afigure);
  337.         pageitems->UU.U8.depthnumber = depth;
  338.     }
  339.  
  340.     /* Assume that pageitems points to Afigure */
  341.     /* traverse the list */
  342.     i = pageitems;        /* point to front of list for now */
  343.     p = i->UU.U8.body->things;
  344.     while (p != NULL)
  345.     {
  346.         if (depth == i->UU.U8.depthnumber)
  347.         {        /* simple push */
  348. /*
  349.  * Note: this is the case when pushing another figure item onto
  350.  * an already-existing list. We push the
  351.  * newfigure with a depth of (fig^.depthnumber - 1) because
  352.  * it really is part of the higer-level figure
  353.  */
  354.             break;
  355.         }
  356.         if (depth <= i->UU.U8.depthnumber)
  357.             continue;
  358.         /* there MUST be a figure with a higher number deeper */
  359.         while (p->kind != Afigure && p->nextitem != NULL)
  360.             p = p->nextitem;
  361.  
  362.         if (p->kind == Afigure)
  363.         {
  364.             i = p;
  365.             p = i->UU.U8.body->things;
  366.         }
  367.         else
  368.         {
  369.             complain(ERRREALBAD);
  370.             fprintf(logfile,
  371.                 "OOPS p^.kind isnt a figure. It must be near endoflist\n");
  372.         }
  373.     }
  374.  
  375.     /*
  376.      * we have the correct front of list-list, and i points to Afigure item
  377.      */
  378.     newthing->nextitem = p;
  379.     i->UU.U8.body->things = newthing;
  380. }
  381.  
  382. static double 
  383. Tgetfixword(k)
  384.     int             k;
  385. {
  386.     short           a;
  387.     int32           f;
  388.  
  389.     a = tfm[k + 100] * 16 + tfm[k + 101] / 16;
  390.     f = ((tfm[k + 101] & 15) * 256 + tfm[k + 102]) * 256 + tfm[k + 103];
  391.     if (a <= 2047)
  392.         return (a + (double) f / TWO20);
  393.     a = 4096 - a;
  394.     if (f > 0)
  395.     {
  396.         f = TWO20 - f;
  397.         a--;
  398.     }
  399.     return (a + (double) f / TWO20);
  400. }
  401.  
  402. static int32 
  403. TgetSigned(k)
  404.     int             k;
  405. {
  406.     int32           i;
  407.  
  408.     i = tfm[k + 100];
  409.     if (i < 128)
  410.         i -= 256;
  411.     return (((i * 256 + tfm[k + 101]) * 256 + tfm[k + 102]) * 256 + tfm[k + 103]);
  412. }
  413.  
  414. /*
  415.  * open a .tfm file and return the parameters in it.
  416.  * Used only in conjuction with the vector and music fonts
  417.  */
  418. static void 
  419. gettfm(tfmfilnam, dessize, p1, p2, p3, p4, p5, p6, p7, cksum)
  420.     charstring      tfmfilnam;
  421.     int32          *dessize, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *cksum;
  422. {
  423.     int32           tfmptr, lf, lh, bc, ec, nw, nh, nd, ni, nl, nk, ne, np, charbase, widthbase, heightbase, depthbase,
  424.                     italicbase, ligkernbase, kernbase, extenbase, parambase;
  425.     ScaledPts       tempdesignsize;
  426.  
  427.     *p1 = 0;
  428.     *p2 = 0;
  429.     *p3 = 0;
  430.     *p4 = 0;
  431.     *p5 = 0;
  432.     *p6 = 0;
  433.     *p7 = 0;
  434.     *cksum = -1;
  435.     if (!opentfmfile(tfmfilnam))
  436.     {
  437.         complain(ERRREALBAD);
  438.         fprintf(logfile, "%s---not loaded, TFM file can't be opened!\n", tfmfilnam);
  439.         jumpout();
  440.     }
  441.     tfm[100] = Tgetc();
  442.     tfm[101] = Tgetc();
  443.     lf = tfm[100] * 256 + tfm[101];
  444.     if (lf * 4 - 1 > TFMSIZE)
  445.     {
  446.         complain(ERRREALBAD);
  447.         fprintf(logfile, "The tfm file:%s is bigger than I can handle!\n", tfmfilnam);
  448.         return;
  449.     }
  450.     for (tfmptr = 102; tfmptr <= lf * 4 + 99; tfmptr++)
  451.         tfm[tfmptr] = Tgetc();
  452.     tfmptr = 2;
  453.     lh = tfm[tfmptr + 100] * 256 + tfm[tfmptr + 101];
  454.     tfmptr += 2;
  455.     bc = tfm[tfmptr + 100] * 256 + tfm[tfmptr + 101];
  456.     tfmptr += 2;
  457.     ec = tfm[tfmptr + 100] * 256 + tfm[tfmptr + 101];
  458.     tfmptr += 2;
  459.     nw = tfm[tfmptr + 100] * 256 + tfm[tfmptr + 101];
  460.     tfmptr += 2;
  461.     nh = tfm[tfmptr + 100] * 256 + tfm[tfmptr + 101];
  462.     tfmptr += 2;
  463.     nd = tfm[tfmptr + 100] * 256 + tfm[tfmptr + 101];
  464.     tfmptr += 2;
  465.     ni = tfm[tfmptr + 100] * 256 + tfm[tfmptr + 101];
  466.     tfmptr += 2;
  467.     nl = tfm[tfmptr + 100] * 256 + tfm[tfmptr + 101];
  468.     tfmptr += 2;
  469.     nk = tfm[tfmptr + 100] * 256 + tfm[tfmptr + 101];
  470.     tfmptr += 2;
  471.     ne = tfm[tfmptr + 100] * 256 + tfm[tfmptr + 101];
  472.     tfmptr += 2;
  473.     np = tfm[tfmptr + 100] * 256 + tfm[tfmptr + 101];
  474.     tfmptr += 2;
  475.     if (lf != lh + ec - bc + nw + nh + nd + ni + nl + nk + ne + np + 7)
  476.     {
  477.         complain(ERRREALBAD);
  478.         fprintf(logfile, "%s: subfile sizes don't add up to the stated total!\n", tfmfilnam);
  479.         fprintf(logfile,
  480.             "Sorry, but I can't go on; are you sure this is a TFM?\n");
  481.         return;
  482.     }
  483.     if (bc > ec + 1 || ec > 255)
  484.     {
  485.         complain(ERRREALBAD);
  486.         fprintf(logfile, "The character code range %ld..%ld is illegal!\n", bc, ec);
  487.         fprintf(logfile, "Sorry, but I can't go on; are you sure this is a TFM?\n");
  488.         return;
  489.     }
  490.     charbase = lh - bc + 6;
  491.     widthbase = charbase + ec + 1;
  492.     heightbase = widthbase + nw;
  493.     depthbase = heightbase + nh;
  494.     italicbase = depthbase + nd;
  495.     ligkernbase = italicbase + ni;
  496.     kernbase = ligkernbase + nl;
  497.     extenbase = kernbase + nk;
  498.     parambase = extenbase + ne - 1;
  499.  
  500.     *dessize = (int32) floor(Tgetfixword(28) * SPPERPT + 0.5);
  501.     /* now in ScaledPts */
  502.     tempdesignsize = (int32) floor(*dessize * magfactor + 0.5);
  503.     *cksum = TgetSigned(24);
  504.     /* return the special 7 parameters for the  font */
  505.     *p1 = (int32) floor(Tgetfixword((parambase + 1) * 4) * tempdesignsize + 0.5);
  506.     *p2 = (int32) floor(Tgetfixword((parambase + 2) * 4) * tempdesignsize + 0.5);
  507.     *p3 = (int32) floor(Tgetfixword((parambase + 3) * 4) * tempdesignsize + 0.5);
  508.     *p4 = (int32) floor(Tgetfixword((parambase + 4) * 4) * tempdesignsize + 0.5);
  509.     *p5 = (int32) floor(Tgetfixword((parambase + 5) * 4) * tempdesignsize + 0.5);
  510.     *p6 = (int32) floor(Tgetfixword((parambase + 6) * 4) * tempdesignsize + 0.5);
  511.     *p7 = (int32) floor(Tgetfixword((parambase + 7) * 4) * tempdesignsize + 0.5);
  512. }
  513.  
  514. static void 
  515. initVnMnLtables()
  516. {
  517.     int32           i;
  518.  
  519.     for (i = 0; i < SizVFontTable; i++)
  520.         VFontTable[i] = NULL;
  521.     for (i = 0; i < SizMFontTable; i++)
  522.         MFontTable[i] = NULL;
  523.     for (i = 0; i < SizLFontTable; i++)
  524.         LFontTable[i] = NULL;
  525.     VFontsDefd = 0;
  526.     MFontsDefd = 0;
  527.     LFontsDefd = 0;
  528. }
  529.  
  530. static void 
  531. fonttobedefined(kind, findex)
  532.     char            kind;
  533.     int             findex;
  534. {
  535.     FTBDs++;
  536.     /*
  537.      * reset this to zero after outputting 1. fontdefs 2. bop
  538.      * 3. contents of dvi page 4. eop
  539.      */
  540.     TBD[FTBDs - 1].which = kind;
  541.     TBD[FTBDs - 1].indx = findex;
  542. }
  543.  
  544. static void 
  545. enterfont(fontnum, ck, scalefact, dessiz, nam)
  546.     int32           fontnum, ck, scalefact, dessiz;
  547.     charstring      nam;
  548. {
  549.     int32           n, len;
  550.  
  551.     cmd1byte(FONTDEF);
  552.     cmd2byte(fontnum);
  553.     cmd4byte(ck);
  554.     cmd4byte(scalefact);
  555.     cmd4byte(dessiz);
  556.     cmd1byte(USESTDAREA);
  557.     cmd1byte(len = strlen(nam) - 4);/* skip the length of the .tfm suffix */
  558.     for (n = 0; n < len; n++)    /* skip the .tfm suffix */
  559.         cmd1byte(nam[n]);
  560.  
  561. }
  562.  
  563. static void 
  564. Outputfont(fontnum, ck, scalefact, dessiz, nam)
  565.     int32           fontnum, ck, scalefact, dessiz;
  566.     charstring      nam;
  567. {
  568.     int32           n, len;
  569.  
  570.     OutputByte(FONTDEF);
  571.     Output2Byte(fontnum);
  572.     Output4Byte(ck);
  573.     Output4Byte(scalefact);
  574.     Output4Byte(dessiz);
  575.     OutputByte(USESTDAREA);
  576.     /* dont output the default dir prefix, nor the .tfm suffix */
  577.     OutputByte(len = strlen(nam) - 4);
  578.     for (n = 0; n < len; n++)
  579.         OutputByte(nam[n]);
  580.  
  581. }
  582.  
  583. void 
  584. defineNewfonts()
  585. {
  586.     /*
  587.      * this needs to be done before first access to a font
  588.      * on a page later someone else will have to re-define all of them
  589.      * in the postamble
  590.      */
  591.     int32           i, f, FORLIM;
  592.     VectFontInfRec *WITH;
  593.     MusFontInfRec  *WITH1;
  594.     LabFontInfRec  *WITH2;
  595.  
  596.     FORLIM = FTBDs;
  597.     for (i = 0; i < FORLIM; i++)
  598.     {
  599.         if (TBD[i].which == 'V')
  600.         {
  601.             f = TBD[i].indx;
  602.             WITH = VFontTable[f - 1];    /* with */
  603.             if (WITH->Isdefined)
  604.                 continue;
  605.             Outputfont(WITH->DVIFontNum, WITH->Cksum, WITH->DesSize, WITH->DesSize,
  606.                    WITH->FontName);
  607.             WITH->Isdefined = true;
  608.         }        /* if */
  609.         else if (TBD[i].which == 'M')
  610.         {
  611.             f = TBD[i].indx;
  612.             WITH1 = MFontTable[f - 1];    /* with */
  613.             if (WITH1->Isdefined)
  614.                 continue;
  615.             Outputfont(WITH1->DVIFontNum, WITH1->Cksum, WITH1->DesSize,
  616.                    WITH1->DesSize, WITH1->FontName);
  617.             WITH1->Isdefined = true;
  618.         }
  619.         else if (TBD[i].which == 'L')
  620.         {
  621.             f = TBD[i].indx;
  622.             WITH2 = LFontTable[f - 1];    /* with */
  623.             if (WITH2->Isdefined)    /* ### is this right? */
  624.                 continue;
  625.             Outputfont(WITH2->DVIFontNum, WITH2->Cksum, WITH2->DesSize,
  626.                    WITH2->DesSize, WITH2->FontName);
  627.             WITH2->Isdefined = true;
  628.         }
  629.         else
  630.         {
  631.             complain(ERRREALBAD);
  632.             fprintf(logfile, "Unknown type of font to be defined:\"%c\"\n",
  633.                 TBD[i].which);
  634.         }
  635.     }
  636. }
  637.  
  638. static int32 
  639. GetMusFont(stfsiz, fam)
  640.     int32           stfsiz, fam;
  641. {
  642.     charstring      mustfmnam;
  643.     MusIndex        i;
  644.     ScaledPts       design, p1, p2, p3, p4, linesp, gwidth, p7;
  645.     int32           cksm, FORLIM;
  646.     MusFontInfRec  *WITH;
  647.  
  648.     /* see if it already exists */
  649.     FORLIM = MFontsDefd;
  650.     for (i = 1; i <= FORLIM; i++)
  651.     {            /* loop through since there are few */
  652.         WITH = MFontTable[i - 1];
  653.         if (WITH->Staffsize == stfsiz && WITH->Family == fam)
  654.             return (i);
  655.     }
  656.  
  657.     sprintf(mustfmnam, "mus%c%c.tfm", stfsiz + '0', fam + '0');
  658.     gettfm(mustfmnam, &design, &p1, &p2, &p3, &p4, &linesp, &gwidth, &p7, &cksm);
  659.  
  660.     MFontsDefd++;
  661.     if (MFontsDefd > SizMFontTable)
  662.     {
  663.         complain(ERRREALBAD);
  664.         fprintf(logfile, "%s---not loadable. Size of Music Font table too small\n", mustfmnam);
  665.         jumpout();
  666.     }
  667.  
  668.     i = MFontsDefd;
  669.     MFontTable[i - 1] = (MusFontInfRec *) xmalloc(sizeof(MusFontInfRec));
  670.     WITH = MFontTable[i - 1];
  671.  
  672.     WITH->Staffsize = stfsiz;
  673.     WITH->Family = fam;
  674.     WITH->DesSize = design;
  675.     strcpy(WITH->FontName, mustfmnam);
  676.     WITH->Cksum = cksm;
  677.     WITH->ghu = (int32) floor(gwidth / QNOTEGHUS + 0.5);
  678.     WITH->gvu = (int32) floor(linesp / QNOTEGVUS + 0.5);
  679.     WITH->DVIFontNum = GDVIFN++;
  680.     WITH->Isdefined = false;
  681.     /* call someone to do the defns of cdp, cht, cwd foreach beam */
  682.     definebeams(&MFontTable[i - 1]);
  683.     fonttobedefined('M', i);
  684.     return (i);
  685. }
  686.  
  687. int32 
  688. GetVectFont(size, vk)
  689.     VThickness      size;
  690.     VectKind        vk;
  691. {
  692.     charstring      vectfmnam;
  693.     VecIndex        i;
  694.     ScaledPts       design, p1, p2, w0, w1, maxveclen, p6, p7;
  695.     int32           cksm, r, FORLIM;
  696.     VectFontInfRec *WITH;
  697.  
  698.     /* see if it already exists */
  699.     FORLIM = VFontsDefd;
  700.     for (i = 1; i <= FORLIM; i++)
  701.     {            /* with */
  702.         WITH = VFontTable[i - 1];
  703.         if (WITH->psize == size && WITH->vkind == vk)
  704.             return (i);
  705.     }
  706.     switch (vk)
  707.     {
  708.     case VKCirc:
  709.         r = 'c';
  710.         break;
  711.     case VKVert:
  712.         r = 'v';
  713.         break;
  714.     case VKHort:
  715.         r = 'h';
  716.         break;
  717.     }
  718.     sprintf(vectfmnam, "%cvec%d.tfm", r, size);
  719.     gettfm(vectfmnam, &design, &p1, &p2, &w0, &w1, &maxveclen, &p6, &p7, &cksm);
  720.     VFontsDefd++;
  721.     if (VFontsDefd > SizVFontTable)
  722.     {
  723.         complain(ERRREALBAD);
  724.         fprintf(logfile, "%s---not loadable. Size of Vector Font table too small\n", vectfmnam);
  725.         jumpout();
  726.     }
  727.  
  728.     i = VFontsDefd;
  729.     VFontTable[i - 1] = (VectFontInfRec *) xmalloc(sizeof(VectFontInfRec));
  730.     WITH = VFontTable[i - 1];
  731.  
  732.     WITH->vkind = vk;
  733.     WITH->psize = size;
  734.     WITH->DesSize = design;
  735.     if (vk == VKVert)
  736.         WITH->PenSize = w1;
  737.     else
  738.         WITH->PenSize = w0;
  739.     WITH->PenSize = (int32) floor(size * (MAXVECLENsp / 16.0) + 0.5);
  740.     WITH->MaxVectLen = maxveclen;
  741.     strcpy(WITH->FontName, vectfmnam);
  742.     WITH->Cksum = cksm;
  743.     WITH->Isdefined = false;
  744.     WITH->DVIFontNum = GDVIFN++;
  745.  
  746.     definevectors(&VFontTable[i - 1]);
  747.     /* someone asked for it, so they must want it, and we should fntdef it */
  748.     fonttobedefined('V', i);
  749.     return (i);
  750. }
  751.  
  752.  
  753. /*----------------------------------------------------------*/
  754. int32 
  755. GetLabFont(style)
  756.     int32           style;
  757. {
  758.     charstring      labtfmnam;
  759.     int32           i, cksm, FORLIM;
  760.     ScaledPts       design, p1, space, p3, p4, p5, p6, p7;
  761.     LabFontInfRec  *WITH;
  762.  
  763.     if (style > MAXLABELFONTS)
  764.         style = 1;
  765.     FORLIM = LFontsDefd;
  766.     for (i = 1; i <= FORLIM; i++)
  767.     {
  768.         WITH = LFontTable[i - 1];
  769.         if (WITH->internalnumber == style)
  770.             return (i);
  771.     }
  772.  
  773.     switch (style)
  774.     {
  775.     case 1:        /* cmtt10 */
  776.         strcpy(labtfmnam, "cmtt10");
  777.         break;
  778.     case 2:        /* cmb10 */
  779.         strcpy(labtfmnam, "cmb10");
  780.         break;
  781.     case 3:        /* cmsl10 */
  782.         strcpy(labtfmnam, "cmsl10");
  783.         break;
  784.     case 4:        /* cmtt8 */
  785.         strcpy(labtfmnam, "cmtt8");
  786.         break;
  787.     case 5:        /* cmsl8 */
  788.         strcpy(labtfmnam, "cmsl8");
  789.         break;
  790.     }
  791.     strcat(labtfmnam, ".tfm");
  792.     gettfm(labtfmnam, &design, &p1, &space, &p3, &p4, &p5, &p6, &p7, &cksm);
  793.  
  794.     LFontsDefd++;
  795.  
  796.     if (LFontsDefd > SizLFontTable)
  797.     {
  798.         complain(ERRREALBAD);
  799.         fprintf(logfile, "%s---not loadable. Size of Label Font table too small\n", labtfmnam);
  800.         jumpout();
  801.     }
  802.  
  803.     i = LFontsDefd;
  804.     LFontTable[i - 1] = (LabFontInfRec *) xmalloc(sizeof(LabFontInfRec));
  805.     WITH = LFontTable[i - 1];    /* with */
  806.  
  807.     strcpy(WITH->FontName, labtfmnam);
  808.     WITH->Cksum = cksm;
  809.     WITH->DesSize = design;
  810.     WITH->internalnumber = style;
  811.     WITH->spacewidth = space;
  812.     WITH->DVIFontNum = GDVIFN++;
  813.     WITH->Isdefined = false;
  814.     fonttobedefined('L', i);
  815.     return (i);
  816. }
  817.  
  818. static double 
  819. vectangle(dx, dy)
  820.     int32           dx, dy;
  821. {
  822.     if (dx != 0)
  823.         return (atan(dy / (double) dx) * RADTODEG);
  824.     else
  825.         return (dy > 0 ? 90.0 : -90.0);
  826. }
  827.  
  828. static void 
  829. definevectors(Vec)
  830.     VectFontInfRec **Vec;
  831. {
  832.     /* var Vec: pVectFontInfRec */
  833.     int             i;
  834.     double          units;
  835.     VectFontInfRec *V;
  836.     FontInfRec     *F;
  837.     struct vecinfo *v;
  838.  
  839.     V = *Vec;
  840.     units = V->MaxVectLen / 16.0;
  841.     for (i = 0, F = V->FontInfo, v = vectab; i < 128; ++i, ++F, ++v)
  842.     {
  843.         F->Cht = floor(v->Cht * units + 0.5);
  844.         F->Cdp = floor(v->Cdp * units + 0.5);
  845.         F->Cwd = floor(v->Cwd * units + 0.5);
  846.         F->Angle = v->Angle;
  847.     }
  848. }
  849.  
  850. /*
  851.  * If, for some reason, you do not want to deal with music capabilities,
  852.  * replace the body of this procedure with just a begin
  853.  * end; pair  and also the TylBeam proc.
  854.  */
  855. static void 
  856. definebeams(M)
  857.     MusFontInfRec **M;
  858. {
  859.     /* var M : pMusFontInfRec */
  860. }
  861.  
  862. #define UnitRadius      16777216/* TWO24 scaledpts */
  863.  
  864. /*
  865.  * use pre-calculated coordinates of a circle that has a given unit-radius.
  866.  * Scale those points to fit the desired radius
  867.  */
  868. void 
  869. defineCircleCpts(rad, centx, centy, CircleCpt, numpts)
  870.     int32           rad, centx, centy;
  871.     int32        (*CircleCpt)[2];
  872.     int32          *numpts;
  873. {
  874.     double          ratio;
  875.  
  876.     if (rad == 0)
  877.     {
  878.         complain(ERRBAD);
  879.         fprintf(logfile, "Error in fig#%ld on page %ld\n",
  880.             pgfigurenum, currpagenum);
  881.         fprintf(logfile, "Zero length radius for circle! Setting to 1 sp\n");
  882.         rad = 1;
  883.     }
  884.     ratio = float_(rad) / float_(UnitRadius);
  885.     *numpts = 16;
  886.     CircleCpt[1][0] = (int32) floor(ratio * 16777216.00000 + 0.5) + centx;
  887.     CircleCpt[1][1] = centy;/* round (ratio *      0.00000) */
  888.     CircleCpt[2][0] = (int32) floor(ratio * 15500126.47492 + 0.5) + centx;
  889.     CircleCpt[2][1] = (int32) floor(ratio * 6420362.60441 + 0.5) + centy;
  890.     CircleCpt[3][0] = (int32) floor(ratio * 11863283.20303 + 0.5) + centx;
  891.     CircleCpt[3][1] = (int32) floor(ratio * 11863283.20303 + 0.5) + centy;
  892.     CircleCpt[4][0] = (int32) floor(ratio * 6420362.60441 + 0.5) + centx;
  893.     CircleCpt[4][1] = (int32) floor(ratio * 15500126.47492 + 0.5) + centy;
  894.     CircleCpt[5][0] = centx;/* round (ratio *     -0.00000) */
  895.     CircleCpt[5][1] = (int32) floor(ratio * 16777216.00000 + 0.5) + centy;
  896.     CircleCpt[6][0] = (int32) floor(0.5 - ratio * 6420362.60441) + centx;
  897.     CircleCpt[6][1] = (int32) floor(ratio * 15500126.47492 + 0.5) + centy;
  898.     CircleCpt[7][0] = (int32) floor(0.5 - ratio * 11863283.20303) + centx;
  899.     CircleCpt[7][1] = (int32) floor(ratio * 11863283.20303 + 0.5) + centy;
  900.     CircleCpt[8][0] = (int32) floor(0.5 - ratio * 15500126.47492) + centx;
  901.     CircleCpt[8][1] = (int32) floor(ratio * 6420362.60441 + 0.5) + centy;
  902.     CircleCpt[9][0] = (int32) floor(0.5 - ratio * 16777216.00000) + centx;
  903.     CircleCpt[9][1] = centy;/* round (ratio *     -0.00000) */
  904.     CircleCpt[10][0] = (int32) floor(0.5 - ratio * 15500126.47492) + centx;
  905.     CircleCpt[10][1] = (int32) floor(0.5 - ratio * 6420362.60441) + centy;
  906.     CircleCpt[11][0] = (int32) floor(0.5 - ratio * 11863283.20303) + centx;
  907.     CircleCpt[11][1] = (int32) floor(0.5 - ratio * 11863283.20303) + centy;
  908.     CircleCpt[12][0] = (int32) floor(0.5 - ratio * 6420362.60441) + centx;
  909.     CircleCpt[12][1] = (int32) floor(0.5 - ratio * 15500126.47492) + centy;
  910.     CircleCpt[13][0] = centx;    /* round (ratio *      0.00000) */
  911.     CircleCpt[13][1] = (int32) floor(0.5 - ratio * 16777216.00000) + centy;
  912.     CircleCpt[14][0] = (int32) floor(ratio * 6420362.60441 + 0.5) + centx;
  913.     CircleCpt[14][1] = (int32) floor(0.5 - ratio * 15500126.47492) + centy;
  914.     CircleCpt[15][0] = (int32) floor(ratio * 11863283.20303 + 0.5) + centx;
  915.     CircleCpt[15][1] = (int32) floor(0.5 - ratio * 11863283.20303) + centy;
  916.     CircleCpt[16][0] = (int32) floor(ratio * 15500126.47492 + 0.5) + centx;
  917.     CircleCpt[16][1] = (int32) floor(0.5 - ratio * 6420362.60441) + centy;
  918.     /* create the pre-list phantom */
  919.     CircleCpt[0][0] = CircleCpt[16][0];
  920.     CircleCpt[0][1] = CircleCpt[16][1];
  921. }
  922.  
  923. #undef UnitRadius
  924.  
  925. /*
  926.  * compute control points for an arc going from startangle to stopangle, centered at (centx, centy)
  927.  */
  928. void 
  929. definearcpts(rad, centx, centy, startang, stopang, cpts, nknots)
  930.     int32           rad, centx, centy, startang, stopang;
  931.     int32        (*cpts)[2];
  932.     int32          *nknots;
  933. {
  934.     int32           n;
  935.     double          a, b, curr, delta;
  936.     int32           i;
  937.  
  938.     a = startang * DEGTORAD;
  939.     b = stopang * DEGTORAD;
  940.     n = 16;
  941.     if (a > b)
  942.         a -= 2 * PI;
  943.     delta = fabs(b - a) / n;
  944.     if (a == b)
  945.     {
  946.         complain(ERRNOTBAD);
  947.         fprintf(logfile, "Error in compute arc points:: should be a circle\n");
  948.     }
  949.     curr = a;
  950.     i = 1;
  951.     while (curr <= b)
  952.     {            /* make arc about (centx,centy) */
  953.         cpts[i][0] = (int32) floor(rad * cos(curr) + 0.5) + centx;
  954.         cpts[i][1] = (int32) floor(rad * sin(curr) + 0.5) + centy;
  955.         i++;
  956.         curr += delta;
  957.     }
  958.  
  959.     /*
  960.      * go one point beyond -- around the arc so that we can have
  961.      * good smoothness for this phantom point
  962.      */
  963.  
  964.     cpts[i][0] = (int32) floor(rad * cos(b + delta) + 0.5) + centx;
  965.     cpts[i][1] = (int32) floor(rad * sin(b + delta) + 0.5) + centy;
  966.  
  967.     /* and one phantom point before the list */
  968.     cpts[0][0] = (int32) floor(rad * cos(a - delta) + 0.5) + centx;
  969.     cpts[0][1] = (int32) floor(rad * sin(a - delta) + 0.5) + centy;
  970.  
  971.     *nknots = i - 1;
  972. }
  973.  
  974. static int 
  975. isaletter(b)
  976.     int             b;
  977. {
  978.     return (isalpha(b) || b == '@' || b == '"');
  979. }
  980.  
  981. static int 
  982. getnumber(cpp)
  983.     char        **cpp;
  984. {
  985.     int             n;
  986.     int        isneg;
  987.  
  988.     n = 0;
  989.     isneg = false;
  990.     for ( ; **cpp != '\0' && (!isdigit(**cpp)); ++*cpp)
  991.         if (**cpp == '-')
  992.             isneg = true;
  993.     while (isspace(**cpp))    /* Skip spaces */
  994.         ++*cpp;
  995.     for ( ; **cpp != '\0' && isdigit(**cpp); ++*cpp)
  996.         n = n * 10 + **cpp - '0';
  997.     return (isneg ? -n : n);
  998. }
  999.  
  1000. static int 
  1001. getletter(cpp)
  1002.     char        **cpp;
  1003. {
  1004.     char        *cp;
  1005.  
  1006.     cp = *cpp;
  1007.     /* non letter */
  1008.     for (cp = *cpp; *cp != '\0' && !isaletter(*cp) && !isspace(*cp); ++cp)
  1009.         ;
  1010.     if (*cp != '\0' && (isaletter(*cp) ||
  1011.                 (isspace(*cp) && !isdigit(*cp))))
  1012.     {
  1013.         *cpp = cp + 1;
  1014.         return (*cp);
  1015.     }
  1016.     return (' ');
  1017. }
  1018.  
  1019. static int 
  1020. getanything(cpp)
  1021.     char        **cpp;
  1022. {
  1023.     char        c;
  1024.  
  1025.     if ((c = **cpp) != '\0')
  1026.     {
  1027.         ++*cpp;
  1028.         return (c);
  1029.     }
  1030.     return (' ');
  1031. }
  1032.  
  1033. /*****************************************************
  1034.    The following routines look for key - letter tokens
  1035.   that indicate certain attributes for a primitive.
  1036.  
  1037. Currently, the letters used are:
  1038.         Sfor scaled-points measurement
  1039.         Pfor printers points
  1040.         Mmillimeters measurement
  1041.         Cuse a Circular vector for drawing
  1042.         HHorizontal-pen vector
  1043.         VVertical vector
  1044.         BB-spline
  1045.         IInterpolating B-spline
  1046.         KCatmull-Rom spline
  1047.         DCardinal spline
  1048.         UOpen spline
  1049.         Oclosed spline
  1050.         Xput marks on spline control pts
  1051.         TTransformation marker
  1052.         RRegular beam characters
  1053.         GGrace Beam characters
  1054.         @Specify center-point for arc/circle
  1055.         LLine-style
  1056.         Ffor beginfigure: Fit figure to wid/ht
  1057.         Wfor beginfigure: figure was created at this wid & ht
  1058. ***************************************************/
  1059.  
  1060. static void 
  1061. gettransforms(sc1, sc2, r, tr1, tr2, cpp)
  1062.     double         *sc1, *sc2, *r;
  1063.     int32          *tr1, *tr2;
  1064.     char        **cpp;
  1065. {
  1066.     char        *cp;
  1067.  
  1068.     *sc1 = 1.0;
  1069.     *sc2 = 1.0;
  1070.     *tr1 = 0;
  1071.     *tr2 = 0;
  1072.     *r = 0.0;
  1073.     for (cp = *cpp; *cp != '\0'; ++cp)
  1074.     {
  1075.         if (*cp == 't' || *cp == 'T')
  1076.         {
  1077.             if (!isaletter(cp[-1]) && !isaletter(cp[1]))
  1078.             {
  1079.                 /* get transform parameters and modify ptr */
  1080.                 *cpp = cp;
  1081.                 *sc1 = getnumber(cpp) / 100.0;
  1082.                 *sc2 = getnumber(cpp) / 100.0;
  1083.                 *tr1 = getnumber(cpp);
  1084.                 *tr2 = getnumber(cpp);
  1085.                 *r = float_(getnumber(cpp));
  1086.                 /* degrees about primitive center */
  1087.                 if (*r < 0.0)
  1088.                     *r += 360.0;
  1089.                 break;
  1090.             }
  1091.         }
  1092.     }
  1093. }
  1094.  
  1095. static int 
  1096. findmarker(set, cp)
  1097.     char    *set;
  1098.     char    *cp;
  1099. {
  1100.     for ( ; *cp != '\0'; ++cp)
  1101.     {
  1102.         if (strchr(set, *cp))
  1103.             if (!isaletter(cp[-1]) && !isaletter(cp[1]))
  1104.                 return (tolowercase(*cp));
  1105.     }
  1106.     return (0);
  1107. }
  1108.  
  1109. #define    findscale(p)        findmarker("sSpPmM", p)
  1110. #define    findvectkind(p)        findmarker("cChHvV", p)
  1111. #define    findlinestyle(p)    findmarker("lL", p)
  1112. #define    findbeamkind(p)        findmarker("rRgG", p)
  1113. #define    findsplinekind(p)    findmarker("bBiIkKdD", p)
  1114. #define    findsplclosure(p)    findmarker("oOuU", p)
  1115. #define    findatsign(p)        findmarker("@", p)
  1116. #define    finddotmark(p)        findmarker("xX", p)
  1117. #define    findfigdimens(p)    findmarker("wW", p)
  1118. #define    findfitsizes(p)        findmarker("fF", p)
  1119.  
  1120. static double 
  1121. thescaleof(scal)
  1122.     int32           scal;
  1123. {
  1124.     if (scal == 's')
  1125.         return (1 * magfactor);
  1126.     if (scal == 'p')
  1127.         return (SPPERPT * magfactor);
  1128.     if (scal == 'm')
  1129.         return (SPPERMM * magfactor);
  1130.     if (scal == 0)
  1131.         return (SPPERPT * magfactor);
  1132. }
  1133.  
  1134.  
  1135. static VectKind 
  1136. thevectorof(vkin)
  1137.     int32           vkin;
  1138. {
  1139.     if (vkin == 'c')
  1140.         return VKCirc;
  1141.     if (vkin == 'v')
  1142.         return VKVert;
  1143.     if (vkin == 'h')
  1144.         return VKHort;
  1145.     if (vkin == 0)
  1146.         return VKCirc;
  1147. }
  1148.  
  1149. static LineStyle 
  1150. thestyleof(linest)
  1151.     int32           linest;
  1152. {
  1153.     static LineStyle styletab[4] = {solid, dotted, dashed, dotdash};
  1154.  
  1155.     if (linest > 3 || linest < 0)
  1156.         linest = 0;
  1157.     return (styletab[linest]);
  1158. }
  1159.  
  1160. static void 
  1161. tylspecials(cp)
  1162.     char        *cp;
  1163. {
  1164.     /*
  1165.      * specnum is the DVI-number of the special
  1166.      * nbytes is the number of parameter bytes
  1167.      */
  1168.     int32           siz, numknots;    /* Lots of temp vars that we use */
  1169.     int32           x1, y1, x2, y2;
  1170.     double          sx100, sy100, rot, SPscale;
  1171.     ScaledPts       transx, transy, minx, miny, maxx, maxy;
  1172.     ControlPoints   cpts;
  1173.     VThickness      thk;
  1174.     LineStyle       patt;
  1175.     ThickAryType    TTary;
  1176.     VectKind        vk;
  1177.     BeamKind        bk;
  1178.     int32           markdiam, radius, ang1, ang2;
  1179.     charstring      phrase;
  1180.     int32           style;
  1181.     char        nam[5];    /* the first parameter of the \special */
  1182.     char            let;
  1183.     int32           i;
  1184.     Item           *pi;
  1185.     int32           maxthk, minthk;
  1186.     SplineKind      splinetype;
  1187.     int        isclosedspline;
  1188.     int        free PP((char *));
  1189.  
  1190.     /* Lets look for a primitive to tyl */
  1191.     for ( ; !isaletter(*cp) && *cp != '\0'; ++cp)
  1192.         ;
  1193.     /* get the name of the primitive */
  1194.     for (i = 0; isaletter(*cp); ++cp)
  1195.         if (i < 4)
  1196.             nam[i++] = tolowercase(*cp);
  1197.     nam[i] = '\0';
  1198.  
  1199.     /* --- BEGINFIGURE ---- */
  1200.     if (streq(nam, "beginfigure", 3))
  1201.     {
  1202.         multifigure++;
  1203.         i = findscale(cp);
  1204.         SPscale = thescaleof(i);
  1205.  
  1206.         gettransforms(&sx100, &sy100, &rot, &transx, &transy, &cp);
  1207.         /*
  1208.          * store all the primitives on pageitems, and dont output them
  1209.          * until we get a endfigure. this way, we can take
  1210.          * care of dealing with all the primitives according to some
  1211.          * global tranformation for the whole figure
  1212.          */
  1213.         pi = NewItem(Afigure);
  1214.         pi->UU.U8.figtheta = rot;
  1215.         pi->UU.U8.fsx = sx100;
  1216.         pi->UU.U8.fsy = sy100;
  1217.         pi->UU.U8.fdx = (int32) floor(transx * SPscale + 0.5);
  1218.         pi->UU.U8.fdy = (int32) floor(transy * SPscale + 0.5);
  1219.         pi->UU.U8.depthnumber = multifigure;    /* we're at a new level */
  1220.         i = findfigdimens(cp);
  1221.         if (i != 0)
  1222.         {
  1223.             pi->UU.U8.preWid = (int32) floor(getnumber(&cp) * SPscale + 0.5);
  1224.             pi->UU.U8.preHt = (int32) floor(getnumber(&cp) * SPscale + 0.5);
  1225.         }
  1226.         i = findfitsizes(cp);
  1227.         if (i != 0)
  1228.         {        /* with */
  1229.             pi->UU.U8.postWid = (int32) floor(getnumber(&cp) * SPscale + 0.5);
  1230.             pi->UU.U8.postHt = (int32) floor(getnumber(&cp) * SPscale + 0.5);
  1231.         }
  1232.         BackupInBuf(DVIMark() - specstart);
  1233.         pushItem(multifigure - 1, pi);
  1234.         return;
  1235.     }
  1236.     /* ---- ENDFIGURE ---- */
  1237.     if (streq(nam, "endfigure", 3))
  1238.     {
  1239.         multifigure--;
  1240.         if (multifigure < 0)
  1241.         {
  1242.             complain(ERRBAD);
  1243.             fprintf(logfile, "Warning: Too many \"endfigure\"s !");
  1244.             multifigure = 0;
  1245.         }
  1246.         BackupInBuf(DVIMark() - specstart);
  1247.         if (multifigure == 0)
  1248.         {
  1249.             /* go do our set of figures (within figures...) */
  1250.             figurehandle(pageitems, pageitems, 1);
  1251.             free((char *)pageitems);/* #### should maybe garbage collect here */
  1252.             pageitems = NULL;
  1253.         }        /* if */
  1254.         return;
  1255.     }
  1256.  
  1257.     /* --- LINE  --- */
  1258.     if (streq(nam, "line", 3))
  1259.     {
  1260.         i = findscale(cp);
  1261.         SPscale = thescaleof(i);
  1262.  
  1263.         gettransforms(&sx100, &sy100, &rot, &transx, &transy, &cp);
  1264.         thk = getnumber(&cp);    /* get the vector thickness */
  1265.         if (thk < 1)
  1266.         {
  1267.             complain(ERRBAD);
  1268.             fprintf(logfile, "?? Thickness not found. Setting to 1\n");
  1269.             thk = 1;
  1270.         }
  1271.         i = findvectkind(cp);
  1272.         vk = thevectorof(i);
  1273.  
  1274.         i = findlinestyle(cp);
  1275.         if (i != 0)
  1276.             patt = thestyleof(getnumber(&cp));
  1277.         else
  1278.             patt = solid;
  1279.  
  1280.         x1 = (int32) floor(getnumber(&cp) * SPscale + 0.5);
  1281.         y1 = (int32) floor(getnumber(&cp) * SPscale + 0.5);
  1282.         x2 = (int32) floor(getnumber(&cp) * SPscale + 0.5);
  1283.         y2 = (int32) floor(getnumber(&cp) * SPscale + 0.5);
  1284.  
  1285.         minx = min(x1, x2);
  1286.         maxx = max(x1, x2);
  1287.         miny = min(y1, y2);
  1288.         maxy = max(y1, y2);
  1289.  
  1290.         BackupInBuf(DVIMark() - specstart);
  1291.         cmd1byte(OURFONTFLAG);
  1292.         linehandle(multifigure, SPscale, x1, y1, x2, y2, 0, 0, thk, vk, patt,
  1293.                minx, maxx, miny, maxy, transx, transy, sx100, sy100, rot);
  1294.     }            /* line */
  1295.     else if (streq(nam, "spline", 3) || streq(nam, "ttspline", 3))
  1296.     {
  1297.         i = findscale(cp);
  1298.         SPscale = thescaleof(i);
  1299.  
  1300.         gettransforms(&sx100, &sy100, &rot, &transx, &transy, &cp);
  1301.  
  1302.         if (streq(nam, "spline", 3))
  1303.         {
  1304.             thk = getnumber(&cp);
  1305.             if (thk < 1)
  1306.             {
  1307.                 complain(ERRBAD);
  1308.                 fprintf(logfile, "Spline Thickness not found. Setting to 1\n");
  1309.                 thk = 1;
  1310.             }
  1311.         }
  1312.         i = findvectkind(cp);
  1313.         vk = thevectorof(i);
  1314.  
  1315.         i = findlinestyle(cp);
  1316.         if (i != 0)
  1317.             patt = thestyleof(getnumber(&cp));
  1318.         else
  1319.             patt = solid;
  1320.  
  1321.         i = findsplinekind(cp);
  1322.         if (i == 'b')
  1323.             splinetype = BSPL;
  1324.         else if (i == 'i')
  1325.             splinetype = INTBSPL;
  1326.         else if (i == 'k')
  1327.             splinetype = CATROM;
  1328.         else if (i == 'd')
  1329.             splinetype = CARD;
  1330.         else if (i == 0)
  1331.             splinetype = CATROM;
  1332.  
  1333.         i = findsplclosure(cp);
  1334.         if (i == 'o')
  1335.             isclosedspline = true;
  1336.         else if (i == 'u')
  1337.             isclosedspline = false;
  1338.         else if (i == 0)
  1339.             isclosedspline = false;
  1340.  
  1341.         i = finddotmark(cp);
  1342.         if (i == 'x')
  1343.             markdiam = getnumber(&cp);
  1344.         else if (i == 0)
  1345.             markdiam = 0;
  1346.  
  1347.         numknots = min(getnumber(&cp), (int32) MAXCTLPTS);
  1348.         if (numknots < 1)
  1349.         {
  1350.             complain(ERRBAD);
  1351.             fprintf(logfile,
  1352.                 "Number of spline/ttspline knot points not found. Setting to 1\n");
  1353.             numknots = 1;
  1354.         }
  1355.  
  1356.         minx = TWO24;
  1357.         miny = TWO24;
  1358.         maxx = -TWO24;
  1359.         maxy = -TWO24;
  1360.  
  1361.         for (i = 0; i <= numknots + 3; i++)
  1362.         {
  1363.             cpts[i][0] = 0;
  1364.             cpts[i][1] = 0;
  1365.         }        /* for */
  1366.  
  1367.         for (i = 1; i <= numknots; i++)
  1368.         {
  1369.             x1 = (int32) floor(getnumber(&cp) * SPscale + 0.5);
  1370.             cpts[i][0] = x1;
  1371.             if (x1 < minx)
  1372.                 minx = x1;
  1373.             if (x1 > maxx)
  1374.                 maxx = x1;
  1375.             y1 = (int32) floor(getnumber(&cp) * SPscale + 0.5);
  1376.             cpts[i][1] = y1;
  1377.             if (y1 < miny)
  1378.                 miny = y1;
  1379.             if (y1 > maxy)
  1380.                 maxy = y1;
  1381.         }        /* for */
  1382.  
  1383.         if (streq(nam, "ttspline", 3))
  1384.         {
  1385.             for (i = 1; i <= numknots; i++)
  1386.                 TTary[i] = getnumber(&cp);
  1387.         }
  1388.  
  1389.         BackupInBuf(DVIMark() - specstart);
  1390.         cmd1byte(OURFONTFLAG);
  1391.  
  1392.         if (streq(nam, "spline", 3))
  1393.             splinehandle(multifigure, SPscale, splinetype, isclosedspline, markdiam,
  1394.                      cpts, numknots, 0, 0, thk, vk, patt, minx, maxx, miny,
  1395.                      maxy, transx, transy, sx100, sy100, rot);
  1396.         else
  1397.             ttsplhandle(multifigure, SPscale, splinetype, isclosedspline, markdiam,
  1398.                     cpts, TTary, numknots, 0, 0, vk, patt, minx, maxx, miny,
  1399.                     maxy, transx, transy, sx100, sy100, rot);
  1400.     }
  1401.     else if (streq(nam, "beam", 4))
  1402.     {
  1403.         i = findscale(cp);
  1404.         SPscale = thescaleof(i);
  1405.  
  1406.         /* no transforms */
  1407.  
  1408.         siz = getnumber(&cp);    /* the staffsize */
  1409.         i = findbeamkind(cp);
  1410.         if (i == 'g')
  1411.             bk = grace;
  1412.         else if (i == 'r')
  1413.             bk = regular;
  1414.         else if (i == 0)
  1415.             bk = regular;
  1416.  
  1417.         x1 = (int32) floor(getnumber(&cp) * SPscale + 0.5);
  1418.         y1 = (int32) floor(getnumber(&cp) * SPscale + 0.5);
  1419.         x2 = (int32) floor(getnumber(&cp) * SPscale + 0.5);
  1420.         y2 = (int32) floor(getnumber(&cp) * SPscale + 0.5);
  1421.  
  1422.         BackupInBuf(DVIMark() - specstart);
  1423.         cmd1byte(OURFONTFLAG);
  1424.  
  1425.         beamhandle(multifigure, siz, bk, x1, y1, x2, y2);
  1426.     }
  1427.     else if (streq(nam, "tieslur", 3))
  1428.     {
  1429.         i = findscale(cp);
  1430.         SPscale = thescaleof(i);
  1431.  
  1432.         minthk = getnumber(&cp);
  1433.         if (minthk < 1)
  1434.         {
  1435.             complain(ERRBAD);
  1436.             fprintf(logfile, "Tie/Slur Min Thickness not found. Setting to 1\n");
  1437.             minthk = 1;
  1438.         }
  1439.  
  1440.         maxthk = getnumber(&cp);
  1441.         if (maxthk < 1)
  1442.         {
  1443.             complain(ERRBAD);
  1444.             fprintf(logfile, "Tie/Slur MaxThickness not found. Setting to 1\n");
  1445.             maxthk = 1;
  1446.         }
  1447.  
  1448.         numknots = min(getnumber(&cp), (int32) MAXCTLPTS);
  1449.         if (numknots < 1)
  1450.         {
  1451.             complain(ERRBAD);
  1452.             fprintf(logfile,
  1453.                 "Tie/Slur Number of knot points not found. Setting to 1. Should be 5\n");
  1454.             numknots = 1;
  1455.         }
  1456.         for (i = 1; i <= numknots; i++)
  1457.         {
  1458.             cpts[i][0] = (int32) floor(getnumber(&cp) * SPscale + 0.5);
  1459.             cpts[i][1] = (int32) floor(getnumber(&cp) * SPscale + 0.5);
  1460.         }        /* for */
  1461.         BackupInBuf(DVIMark() - specstart);
  1462.         cmd1byte(OURFONTFLAG);
  1463.  
  1464.         tieslurhandle(multifigure, cpts, numknots, (int) minthk, (int) maxthk);
  1465.     }
  1466.     else if (streq(nam, "arc", 3))
  1467.     {
  1468.         i = findscale(cp);
  1469.         SPscale = thescaleof(i);
  1470.  
  1471.         gettransforms(&sx100, &sy100, &rot, &transx, &transy, &cp);
  1472.  
  1473.         thk = getnumber(&cp);
  1474.         if (thk < 1)
  1475.         {
  1476.             complain(ERRBAD);
  1477.             fprintf(logfile, "Arc Thickness not found. Setting to 1\n");
  1478.             thk = 1;
  1479.         }
  1480.         i = findvectkind(cp);
  1481.         vk = thevectorof(i);
  1482.  
  1483.         i = findlinestyle(cp);
  1484.         if (i != 0)
  1485.             patt = thestyleof(getnumber(&cp));
  1486.         else
  1487.             patt = solid;
  1488.  
  1489.         radius = (int32) floor(getnumber(&cp) * SPscale + 0.5);
  1490.         if (radius == 0)
  1491.             radius = (int32) floor(1 * SPscale + 0.5);
  1492.         i = findatsign(cp);
  1493.         if (i != 0)
  1494.         {
  1495.             x2 = (int32) floor(getnumber(&cp) * SPscale + 0.5);
  1496.             y2 = (int32) floor(getnumber(&cp) * SPscale + 0.5);
  1497.         }
  1498.         else
  1499.         {
  1500.             x2 = 0;
  1501.             y2 = 0;    /* assume center at origin */
  1502.         }
  1503.  
  1504.         ang1 = getnumber(&cp);
  1505.         if (abs(ang1) > 360)
  1506.         {
  1507.             ang1 %= 360;
  1508.             /*
  1509.              * p2c: x.p, line 5570: Note: Using % for possibly-negative arguments [317]
  1510.              */
  1511.         }
  1512.         ang2 = getnumber(&cp);
  1513.         if (abs(ang2) > 360)
  1514.         {
  1515.             ang2 %= 360;
  1516.             /*
  1517.              * p2c: x.p, line 5573: Note: Using % for possibly-negative arguments [317]
  1518.              */
  1519.         }
  1520.  
  1521.         minx = TWO24;
  1522.         miny = TWO24;
  1523.         maxx = -TWO24;
  1524.         maxy = -TWO24;
  1525.  
  1526.         if (ang1 == ang2)    /* a circle */
  1527.             defineCircleCpts(radius, x2, y2, cpts, &numknots);
  1528.         else        /* a real arc */
  1529.             definearcpts(radius, x2, y2, ang1, ang2, cpts, &numknots);
  1530.  
  1531.         for (i = 1; i <= numknots; i++)
  1532.         {
  1533.             x1 = cpts[i][0];
  1534.             if (x1 < minx)
  1535.                 minx = x1;
  1536.             if (x1 > maxx)
  1537.                 maxx = x1;
  1538.  
  1539.             y1 = cpts[i][1];
  1540.             if (y1 < miny)
  1541.                 miny = y1;
  1542.             if (y1 > maxy)
  1543.                 maxy = y1;
  1544.         }        /* for */
  1545.  
  1546.         BackupInBuf(DVIMark() - specstart);
  1547.         cmd1byte(OURFONTFLAG);
  1548.  
  1549.  
  1550.         arccirclehandle(multifigure, SPscale, x2, y2, radius, ang1, ang2, cpts,
  1551.                 numknots, 0, 0, thk, vk, patt, minx, maxx, miny, maxy,
  1552.                 transx, transy, sx100, sy100, rot);
  1553.     }
  1554.     else if (streq(nam, "label", 3))
  1555.     {
  1556.         i = findscale(cp);
  1557.         SPscale = thescaleof(i);
  1558.  
  1559.         style = getnumber(&cp);    /* font style number */
  1560.         if (style < 1 || style > MAXLABELFONTS)
  1561.         {
  1562.             complain(ERRBAD);
  1563.             fprintf(logfile, "Label style bad? Setting to Style 1\n");
  1564.             style = 1;
  1565.         }
  1566.  
  1567.         x1 = (int32) floor(getnumber(&cp) * SPscale + 0.5);
  1568.         y1 = (int32) floor(getnumber(&cp) * SPscale + 0.5);
  1569.  
  1570.         let = getletter(&cp);
  1571.         while (let != '"')
  1572.             let = getletter(&cp);
  1573.         let = getanything(&cp);    /* get next letter or whatever */
  1574.         for (i = 0; let != '"'; ++i)
  1575.         {        /* get the label phrase */
  1576.             phrase[i] = let;
  1577.             let = getanything(&cp);    /* getletter; */
  1578.         }
  1579.         phrase[i] = '\0';
  1580.  
  1581.         BackupInBuf(DVIMark() - specstart);
  1582.         cmd1byte(OURFONTFLAG);
  1583.         labelhandle(multifigure, SPscale, x1, y1, 0, 0, style, phrase, 0, 0);
  1584.     }
  1585.     else if (streq(nam, "param", 3))
  1586.     {
  1587.         i = getnumber(&cp);    /* addressable param number */
  1588.  
  1589.         fprintf(logfile, " I do not know what internal parameter #%ld is\n", i);
  1590.         /* else */
  1591.         BackupInBuf(DVIMark() - specstart);
  1592.     }
  1593.     else
  1594.     {
  1595.         complain(ERRNOTBAD);
  1596.         fprintf(logfile, "Sorry, I don't know how to tyl %s\n", nam);
  1597.     }
  1598. }
  1599.  
  1600. static int
  1601. otherspecials(cp)
  1602.     char        *cp;
  1603. {
  1604.     fprintf(logfile, "Special: %s\n", cp);
  1605.     return (1);
  1606. }
  1607.  
  1608. static void 
  1609. mainhandlespecials(specnum, nbytes)
  1610.     int32           specnum, nbytes;
  1611. {
  1612.     /*
  1613.      * specnum is the DVI-number of the special
  1614.      * nbytes is the number of parameter bytes
  1615.      */
  1616.     char         sysnam[4];
  1617.     char            *cp, *buf;
  1618.     int32           i;
  1619.     char        *malloc PP((unsigned));
  1620.     int        free PP((char *));
  1621.  
  1622.     specstart = DVIMark() - specnum + 237;
  1623.     ourxpos = h;
  1624.     ourypos = v;        /* note the global DVI (h,v) coords */
  1625.  
  1626.     cp = buf = malloc((unsigned)(nbytes + 1));
  1627.     for (i = 0; i < nbytes; ++i)
  1628.         cp[i] = Dget1byte();
  1629.     cp[i] = '\0';
  1630.  
  1631.     while (isspace(*cp))
  1632.         ++cp;
  1633.     /* get the name of the system --- Hopefully 'tyl' */
  1634.     for (i = 0; *cp != '\0' && *cp != ' '; ++cp)
  1635.         if (i < 3)
  1636.             sysnam[i++] = tolowercase(*cp);
  1637.     sysnam[i] = '\0';    /* end of string */
  1638.     if (streq(sysnam, "tyl", 3))
  1639.         tylspecials(cp);
  1640.     else if (otherspecials(buf))
  1641.         ;
  1642.     else
  1643.         fprintf(logfile, "Unknown special ignored: %s\n", buf);
  1644.     free((char *)buf);
  1645. }
  1646.  
  1647. /*
  1648.  * ==================================================
  1649.  * 
  1650.  * The routines below assume coordinates are already in 4th Quadrant DVI-space
  1651.  * 
  1652.  * =====================================================
  1653.  */
  1654.  
  1655. /*
  1656.  * returns 0 if dy.dx not in font 1 if ok 2 if ok and caller should use two of the "code"s coding scheme requires  0<= [dx, dy]
  1657.  * <= 16 AND that max(dx, abs(dy)) is in [0,1,2,4,8,16]
  1658.  */
  1659. static int32 
  1660. outvector(dx, dy, code)
  1661.     int32           dx, dy, *code;
  1662. {
  1663.     int32           c, result;
  1664.  
  1665.     if (dx < 0)
  1666.         return (0);
  1667.  
  1668.     result = 0;        /* init for potential failure */
  1669.     *code = -1;
  1670.     if (dy < 0)
  1671.         c = dy + dx - max(dx, -dy) * 9 + 160;
  1672.     else
  1673.         c = dy - dx - max(dx, dy) * 7 + 160;
  1674.  
  1675.     /*
  1676.      * here translate to OUR coding scheme and return the correct number
  1677.      * this is needed because "c" thinks the char range
  1678.      * is 0 to 160, while we have only 128 chars
  1679.      */
  1680.  
  1681.     if (c == 0)
  1682.     {            /* special cases */
  1683.         *code = 63;
  1684.         result = 2;
  1685.     }
  1686.     else if (c == 64)
  1687.     {
  1688.         *code = 95;
  1689.         result = 2;
  1690.     }
  1691.     else
  1692.     {
  1693.         result = 1;    /* just one char is fine */
  1694.         if (c >= 1 && c <= 63)    /* c - 33 */
  1695.             *code = c - 1;
  1696.         else if (c >= 80 && c <= 112)
  1697.             *code = c - 17;
  1698.         else if (c >= 120 && c <= 136)
  1699.             *code = c - 24;
  1700.         else if (c >= 140 && c <= 148)
  1701.             *code = c - 27;
  1702.         else if (c >= 150 && c <= 154)
  1703.             *code = c - 28;
  1704.         else if (c == 160)
  1705.             *code = 127;
  1706.     }
  1707.     return result;
  1708. }
  1709.  
  1710. /* take care of a Manhattan (horizontal /vertical) line */
  1711. static void 
  1712. hvline(lx, by, rx, ty, fontindex)
  1713.     int32           lx, by, rx, ty, fontindex;
  1714. {
  1715.     int32           t, rth, x, y, width, height;
  1716.  
  1717.     rth = VFontTable[fontindex - 1]->PenSize;    /* thickness of vector in sp */
  1718.     if (lx == rx)
  1719.     {            /* Vertical line */
  1720.         if (ty > by)
  1721.         {
  1722.             t = by;
  1723.             by = ty;
  1724.             ty = t;    /* swap */
  1725.         }
  1726.         x = (int32) floor(lx - rth / 2.0 + 0.5);
  1727.         y = by;
  1728.         width = rth;
  1729.         height = by - ty;
  1730.     }
  1731.     else
  1732.     {            /* Horizontal line */
  1733.         if (ty < by)
  1734.         {
  1735.             t = by;
  1736.             by = ty;
  1737.             ty = t;    /* swap */
  1738.         }
  1739.         if (lx > rx)
  1740.         {
  1741.             t = lx;
  1742.             lx = rx;
  1743.             rx = t;    /* swap */
  1744.         }
  1745.         x = lx;
  1746.  
  1747.         y = by + rth / 2;    /* + rth for {h,v}-space */
  1748.         width = rx - lx;
  1749.         height = rth;
  1750.     }
  1751.  
  1752.     isetpos(x, y);
  1753.     cmd1byte(PUTRULE);
  1754.     cmd4byte(height);
  1755.     cmd4byte(width);
  1756.  
  1757.     /*
  1758.      * output two dots on ends of the rules at    lx, by  and rx, ty
  1759.      */
  1760.     /* the font has already been set before these calls */
  1761.     Tyldot(lx, by);
  1762.     Tyldot(rx, ty);
  1763.     isetpos(rx, ty);
  1764. }
  1765.  
  1766.  
  1767. /* Local variables for diagonal: */
  1768. struct LOC_diagonal
  1769. {
  1770.     int32           xl, yb, xr, yt, curx, cury;
  1771.     double          slope;
  1772.     ScaledPts       mxveclen;
  1773. };
  1774.  
  1775. /* compute maximum length vector character that we  can use */
  1776. static void 
  1777. getincr(outdx, outdy, LINK)
  1778.     int32          *outdx, *outdy;
  1779.     struct LOC_diagonal *LINK;
  1780. {
  1781.     int32           radius, x, y, sign;
  1782.  
  1783.     radius = LINK->mxveclen;/* radius of semi-square */
  1784.     /*
  1785.      * make sure the pt is outside of the semi-square, scaling down radius if necessary
  1786.      */
  1787.     while (LINK->xr - LINK->curx < radius &&
  1788.            abs(LINK->yt - LINK->cury) < radius)
  1789.         radius /= 2;
  1790.     if (LINK->slope < 0.0)    /* <0 since in 4th quad by now */
  1791.         sign = -1;
  1792.     else
  1793.         sign = 1;
  1794.     if (LINK->xr == LINK->curx)
  1795.     {
  1796.         *outdx = 0;
  1797.         *outdy = sign * radius;
  1798.         return;
  1799.     }
  1800.     if (LINK->yt == LINK->cury)
  1801.     {
  1802.         *outdx = abs(radius);
  1803.         *outdy = 0;
  1804.         return;
  1805.     }
  1806.  
  1807.     /*
  1808.      * compute the intersection with the semi-square, choose whichever slope is best
  1809.      */
  1810.     if (fabs(LINK->slope) < 1.0)
  1811.     {            /* mostly horizontal */
  1812.         *outdx = abs(radius);
  1813.         y = LINK->yb +
  1814.             (int32) floor((LINK->curx + abs(radius) - LINK->xl) * LINK->slope + 0.5);
  1815.         *outdy = y - LINK->cury;
  1816.     }
  1817.     else
  1818.     {            /* mostly vertical */
  1819.         x = LINK->xl +
  1820.             (int32) floor((LINK->cury + sign * radius - LINK->yb) / LINK->slope + 0.5);
  1821.         *outdx = x - LINK->curx;
  1822.         *outdy = sign * radius;
  1823.     }
  1824.  
  1825.     if (abs(*outdy) > abs(LINK->yt - LINK->cury))    /* truncate */
  1826.         *outdy = LINK->yt - LINK->cury;
  1827.     if (*outdx > LINK->xr - LINK->curx)    /* truncate */
  1828.         *outdx = LINK->xr - LINK->curx;
  1829.     if (*outdx < 0)
  1830.         *outdx = 0;
  1831.  
  1832.     /*
  1833.      * method to find the exact intersection of the line segment with the semi-circle, used to determine the x and y
  1834.      * values:: we do this by using the arctangent of the slope as the angle 'a' from the x-axis. Then use the relation y =
  1835.      * r cos a, and x = r sin a we can be smart about all this trig stuff by using the relation : sin (arctan a) = 1/sqrt(1
  1836.      * + a^2) cos (arctan a) = a/sqrt(1 + a^2) Thus: q := (1.0 / sqrt (slope * slope + 1.0)); outdx := round (q * radius);
  1837.      * outdy := round (q * radius * slope);
  1838.      * 
  1839.      * Unfortunately, we cannot access the Vector Font coding scheme because the outdx, outdy 's produced here do no conform
  1840.      * to the condition max (dx, abs(dy)) in [0,1,2,4,8,16] when converted to vector-font sizes with sptovecs (see  the
  1841.      * 'diagonal' proc.).
  1842.      */
  1843. }
  1844.  
  1845. static void 
  1846. diagonal(xl_, yb_, xr_, yt_, fontindex)
  1847.     int32           xl_, yb_, xr_, yt_, fontindex;
  1848. {
  1849.     struct LOC_diagonal V;
  1850.     int32           t, dx, dy, code;
  1851.     double          sptovecs;
  1852.     ScaledPts       rho;
  1853.  
  1854.     V.xl = xl_;
  1855.     V.yb = yb_;
  1856.     V.xr = xr_;
  1857.     V.yt = yt_;
  1858.     if (V.xr != V.xl)    /* some illegal value */
  1859.         V.slope = (double) (V.yt - V.yb) / (V.xr - V.xl);
  1860.     else
  1861.         V.slope = BIGREAL;
  1862.  
  1863.     if (V.xl > V.xr)
  1864.     {
  1865.         t = V.xl;
  1866.         V.xl = V.xr;
  1867.         V.xr = t;
  1868.         t = V.yb;
  1869.         V.yb = V.yt;
  1870.         V.yt = t;
  1871.     }            /* swap */
  1872.  
  1873.     V.curx = V.xl;
  1874.     V.cury = V.yb;
  1875.     V.mxveclen = VFontTable[fontindex - 1]->MaxVectLen;
  1876.     rho = V.mxveclen / 16;    /* minimum radius of vector fonts */
  1877.     if (rho == 0)
  1878.     {
  1879.         complain(ERRREALBAD);
  1880.         fprintf(logfile,
  1881.             "Diagonal: Min radius of vector font is zero. setting to 1\n");
  1882.         rho = 1;
  1883.     }
  1884.  
  1885.     if (abs(V.xl - V.xr) <= rho && abs(V.yb - V.yt) <= rho)
  1886.     {            /* pretty much a null line */
  1887.         Tyldot(V.xl, V.yb);
  1888.         return;
  1889.     }
  1890.     sptovecs = 1.0 / rho;    /* conversion for scaled pts to vectorfont units */
  1891.  
  1892.     code = -1;        /* initialize to a bogus number */
  1893.  
  1894.     /*
  1895.      * this conditional really has to have "or" instead of "and", because of lines that are nearly*  horizontal or vertical
  1896.      */
  1897.     while (V.xr - V.curx >= rho || abs(V.yt - V.cury) >= rho)
  1898.     {
  1899.         getincr(&dx, &dy, &V);
  1900.  
  1901.         /*
  1902.          * Get the vector character code corresponding to this approximate incremental amount
  1903.          */
  1904.         t = outvector((int32) floor(dx * sptovecs + 0.5),
  1905.                   (int32) floor(dy * sptovecs + 0.5), &code);
  1906.         /*
  1907.          * Now that we have the character code, go find out its actual physical dimensions for the real dy/dx amounts
  1908.          */
  1909.         if (dy > 0)
  1910.             dy = VFontTable[fontindex - 1]->FontInfo[code].Cdp;
  1911.         else
  1912.             dy = -VFontTable[fontindex - 1]->FontInfo[code].Cht;
  1913.  
  1914.         dx = VFontTable[fontindex - 1]->FontInfo[code].Cwd;
  1915.  
  1916.         switch (t)
  1917.         {
  1918.  
  1919.         case 0:
  1920.             complain(ERRREALBAD);
  1921.             fprintf(logfile, "Error in Diagonal:: bad dydx\n");
  1922.             break;
  1923.  
  1924.         case 1:
  1925.             isetpos(V.curx, V.cury);
  1926.             iputchar(code);
  1927.             break;
  1928.  
  1929.         case 2:
  1930.             isetpos(V.curx, V.cury);
  1931.             iputchar(code);
  1932.             isetpos(V.curx + dx / 2, V.cury + dy / 2);
  1933.             iputchar(code);
  1934.             break;
  1935.         }        /* case */
  1936.  
  1937.         V.curx += dx;
  1938.         V.cury += dy;
  1939.     }            /* while */
  1940.     /*
  1941.      * Get the approximate incremental amount. We use this dy/dx pair in order to index into our vector font coding scheme
  1942.      */
  1943.  
  1944.  
  1945.     if (code >= 0 && V.xr - V.curx >= rho && abs(V.yt - V.cury) >= rho)
  1946.         iputchar(code);
  1947.  
  1948.     /* not null line */
  1949. }
  1950.  
  1951.  
  1952. /* Local variables for tylBrokenLine: */
  1953. struct LOC_tylBrokenLine
  1954. {
  1955.     int32           fontindex;
  1956.     LineStyle       line_type;
  1957.     int        useXaxis;
  1958.     int32           a0, b0, a1, b1, a2, a3, b2, b3, gap, dot, dash;
  1959.     double          s, z;
  1960.     int32           J, frame, Dotgap, Dotdot, Dashgap, Dashdash, DDotgap, DDotdot, DDotdash;
  1961. };
  1962.  
  1963. static void 
  1964. spread(lt, extra, T, LINK)
  1965.     LineStyle       lt;
  1966.     int32           extra, T;
  1967.     struct LOC_tylBrokenLine *LINK;
  1968. {
  1969.     if (T == 0)
  1970.     {            /* only partial frame fits */
  1971.         if (LINK->useXaxis)
  1972.             diagonal(LINK->a0, LINK->b0, LINK->a1, LINK->b1, LINK->fontindex);
  1973.         else
  1974.             diagonal(LINK->b0, LINK->a0, LINK->b1, LINK->a1, LINK->fontindex);
  1975.         return;
  1976.     }
  1977.     LINK->J = 0;
  1978.     LINK->s = float_(LINK->b1 - LINK->b0) / float_(LINK->a1 - LINK->a0);
  1979.     LINK->z = float_(extra) / float_(T);
  1980.     switch (lt)
  1981.     {
  1982.  
  1983.     case dotted:
  1984.         do
  1985.         {
  1986.             LINK->a2 = LINK->a0 + LINK->J * LINK->frame;
  1987.             if (extra > 0)
  1988.                 LINK->a2 += (int32) floor(LINK->J * LINK->z + 0.5);
  1989.             LINK->a3 = LINK->a2 + LINK->dot;
  1990.             LINK->b2 = (int32) floor(LINK->s * (LINK->a2 - LINK->a0) + LINK->b0 + 0.5);
  1991.             LINK->b3 = (int32) floor(LINK->s * (LINK->a3 - LINK->a0) + LINK->b0 + 0.5);
  1992.             if (LINK->a3 <= LINK->a1)
  1993.             {
  1994.                 if (LINK->useXaxis)
  1995.                     diagonal(LINK->a2, LINK->b2, LINK->a3, LINK->b3, LINK->fontindex);
  1996.                 else
  1997.                     diagonal(LINK->b2, LINK->a2, LINK->b3, LINK->a3, LINK->fontindex);
  1998.             }
  1999.             LINK->J++;
  2000.         } while (LINK->a3 < LINK->a1);
  2001.         break;
  2002.  
  2003.     case dashed:
  2004.         do
  2005.         {
  2006.             LINK->a2 = LINK->a0 + LINK->J * LINK->frame;
  2007.             if (extra > 0)
  2008.                 LINK->a2 += (int32) floor(LINK->J * LINK->z + 0.5);
  2009.             LINK->a3 = LINK->a2 + LINK->dash;
  2010.             LINK->b2 = (int32) floor(LINK->s * (LINK->a2 - LINK->a0) + LINK->b0 + 0.5);
  2011.             LINK->b3 = (int32) floor(LINK->s * (LINK->a3 - LINK->a0) + LINK->b0 + 0.5);
  2012.             if (LINK->a3 <= LINK->a1)
  2013.             {
  2014.                 if (LINK->useXaxis)
  2015.                     diagonal(LINK->a2, LINK->b2, LINK->a3, LINK->b3, LINK->fontindex);
  2016.                 else
  2017.                     diagonal(LINK->b2, LINK->a2, LINK->b3, LINK->a3, LINK->fontindex);
  2018.             }
  2019.             LINK->J++;
  2020.         } while (LINK->a3 < LINK->a1);
  2021.         break;
  2022.  
  2023.     case dotdash:
  2024.         do
  2025.         {
  2026.             LINK->a2 = LINK->a0 + LINK->J * LINK->frame;
  2027.             if (extra > 0)
  2028.                 LINK->a2 += (int32) floor(LINK->J * LINK->z + 0.5);
  2029.             LINK->a3 = LINK->a2 + LINK->dash;
  2030.             LINK->b2 = (int32) floor(LINK->s * (LINK->a2 - LINK->a0) + LINK->b0 + 0.5);
  2031.             LINK->b3 = (int32) floor(LINK->s * (LINK->a3 - LINK->a0) + LINK->b0 + 0.5);
  2032.             if (LINK->a3 <= LINK->a1)
  2033.             {
  2034.                 if (LINK->useXaxis)
  2035.                     diagonal(LINK->a2, LINK->b2, LINK->a3, LINK->b3, LINK->fontindex);
  2036.                 else
  2037.                     diagonal(LINK->b2, LINK->a2, LINK->b3, LINK->a3, LINK->fontindex);
  2038.                 LINK->a2 = LINK->a3 + LINK->gap;
  2039.                 if (extra > 0)
  2040.                     LINK->a2 += (int32) floor(LINK->z * 0.5 + 0.5);
  2041.                 LINK->a3 = LINK->a2 + LINK->dot;
  2042.                 LINK->b2 = (int32) floor(LINK->s * (LINK->a2 - LINK->a0) + LINK->b0 + 0.5);
  2043.                 LINK->b3 = (int32) floor(LINK->s * (LINK->a3 - LINK->a0) + LINK->b0 + 0.5);
  2044.                 if (LINK->a3 <= LINK->a1)
  2045.                 {
  2046.                     if (LINK->useXaxis)
  2047.                         diagonal(LINK->a2, LINK->b2, LINK->a3, LINK->b3, LINK->fontindex);
  2048.                     else
  2049.                         diagonal(LINK->b2, LINK->a2, LINK->b3, LINK->a3, LINK->fontindex);
  2050.                 }
  2051.             }
  2052.             LINK->J++;
  2053.         } while (LINK->a3 < LINK->a1);
  2054.         break;
  2055.     }
  2056. }                /* spread */
  2057.  
  2058. static void 
  2059. balance(lt, extra, T, LINK)
  2060.     LineStyle       lt;
  2061.     int32           extra, T;
  2062.     struct LOC_tylBrokenLine *LINK;
  2063. {
  2064.     if (T == 0)
  2065.     {            /* only partial frame fits */
  2066.         if (LINK->useXaxis)
  2067.             diagonal(LINK->a0, LINK->b0, LINK->a1, LINK->b1, LINK->fontindex);
  2068.         else
  2069.             diagonal(LINK->b0, LINK->a0, LINK->b1, LINK->a1, LINK->fontindex);
  2070.         return;
  2071.     }
  2072.     LINK->J = 0;
  2073.     LINK->s = float_(LINK->b1 - LINK->b0) / float_(LINK->a1 - LINK->a0);
  2074.     switch (lt)
  2075.     {
  2076.  
  2077.     case dashed:
  2078.         do
  2079.         {
  2080.             LINK->a2 = LINK->a0 + LINK->J * LINK->frame - extra / 2;
  2081.             LINK->a3 = LINK->a2 + LINK->dash;
  2082.             if (LINK->J == 0)
  2083.                 LINK->a2 = LINK->a0;
  2084.             if (LINK->a3 > LINK->a1)
  2085.                 LINK->a3 = LINK->a1;
  2086.             LINK->b2 = (int32) floor(LINK->s * (LINK->a2 - LINK->a0) + LINK->b0 + 0.5);
  2087.             LINK->b3 = (int32) floor(LINK->s * (LINK->a3 - LINK->a0) + LINK->b0 + 0.5);
  2088.             if (LINK->a3 <= LINK->a1)
  2089.             {
  2090.                 if (LINK->useXaxis)
  2091.                     diagonal(LINK->a2, LINK->b2, LINK->a3, LINK->b3, LINK->fontindex);
  2092.                 else
  2093.                     diagonal(LINK->b2, LINK->a2, LINK->b3, LINK->a3, LINK->fontindex);
  2094.             }
  2095.             LINK->J++;
  2096.         } while (LINK->a3 < LINK->a1);
  2097.         break;
  2098.  
  2099.     case dotdash:
  2100.         do
  2101.         {
  2102.             LINK->a2 = LINK->a0 + LINK->J * LINK->frame - extra / 2;
  2103.             LINK->a3 = LINK->a2 + LINK->dash;
  2104.             if (LINK->J == 0)
  2105.                 LINK->a2 = LINK->a0;
  2106.             if (LINK->a3 > LINK->a1)
  2107.                 LINK->a3 = LINK->a1;
  2108.             LINK->b2 = (int32) floor(LINK->s * (LINK->a2 - LINK->a0) + LINK->b0 + 0.5);
  2109.             LINK->b3 = (int32) floor(LINK->s * (LINK->a3 - LINK->a0) + LINK->b0 + 0.5);
  2110.             if (LINK->a3 <= LINK->a1)
  2111.             {
  2112.                 if (LINK->useXaxis)
  2113.                     diagonal(LINK->a2, LINK->b2, LINK->a3, LINK->b3, LINK->fontindex);
  2114.                 else
  2115.                     diagonal(LINK->b2, LINK->a2, LINK->b3, LINK->a3, LINK->fontindex);
  2116.                 LINK->a2 = LINK->a3 + LINK->gap;
  2117.                 LINK->a3 = LINK->a2 + LINK->dot;
  2118.                 LINK->b2 = (int32) floor(LINK->s * (LINK->a2 - LINK->a0) + LINK->b0 + 0.5);
  2119.                 LINK->b3 = (int32) floor(LINK->s * (LINK->a3 - LINK->a0) + LINK->b0 + 0.5);
  2120.                 if (LINK->a3 <= LINK->a1)
  2121.                 {
  2122.                     if (LINK->useXaxis)
  2123.                         diagonal(LINK->a2, LINK->b2, LINK->a3, LINK->b3, LINK->fontindex);
  2124.                     else
  2125.                         diagonal(LINK->b2, LINK->a2, LINK->b3, LINK->a3, LINK->fontindex);
  2126.                 }
  2127.             }
  2128.             LINK->J++;
  2129.         } while (LINK->a3 < LINK->a1);
  2130.         break;
  2131.     }
  2132. }                /* balance */
  2133.  
  2134. static int32 
  2135. project(I, LINK)
  2136.     int32           I;
  2137.     struct LOC_tylBrokenLine *LINK;
  2138. {
  2139.     int32           K;    /* gives the projection of lengths onto axes */
  2140.  
  2141.     K = (int32) floor(I * float_(abs(LINK->a1 - LINK->a0)) / LINK->s + 0.5);
  2142.     if (K == 0)
  2143.         K = 1;
  2144.     return K;
  2145. }
  2146.  
  2147. static void 
  2148. setlengths(findex, LINK)
  2149.     int32           findex;
  2150.     struct LOC_tylBrokenLine *LINK;
  2151. {
  2152.     /* sets the "optimal" sizes for textured lines */
  2153.     int32           penrad;
  2154.     VThickness      siz;
  2155.  
  2156.     penrad = VFontTable[findex - 1]->PenSize;
  2157.     siz = VFontTable[findex - 1]->psize;
  2158.  
  2159.     LINK->Dotdot = penrad / siz;
  2160.     LINK->Dotgap = penrad * 6;
  2161.     LINK->Dashdash = penrad * 6;
  2162.     LINK->Dashgap = penrad * 6;
  2163.     LINK->DDotdash = penrad * 6;
  2164.     LINK->DDotgap = penrad * 4;
  2165.     LINK->DDotdot = penrad / siz;
  2166. }
  2167.  
  2168. static void 
  2169. setframesize(LINK)
  2170.     struct LOC_tylBrokenLine *LINK;
  2171. {
  2172.     switch (LINK->line_type)
  2173.     {
  2174.         /* length of frame depends on type of broken line */
  2175.     case solid:
  2176.         LINK->frame = 0;
  2177.         break;
  2178.     case dotted:
  2179.         LINK->frame = LINK->gap + LINK->dot;
  2180.         break;
  2181.     case dashed:
  2182.         LINK->frame = LINK->gap + LINK->dash;
  2183.         break;
  2184.     case dotdash:
  2185.         LINK->frame = LINK->gap * 2 + LINK->dot + LINK->dash;
  2186.         break;
  2187.     }
  2188. }
  2189.  
  2190. static void 
  2191. tylBrokenLine(x0, y0, x1, y1, fontindex_, line_type_)
  2192.     int32           x0, y0, x1, y1, fontindex_;
  2193.     LineStyle       line_type_;
  2194. {
  2195.     struct LOC_tylBrokenLine V;
  2196.     double          fit;
  2197.     int32           T, a1ma0;
  2198.  
  2199.     V.fontindex = fontindex_;
  2200.     V.line_type = line_type_;
  2201.     if (x0 == x1 && y0 == y1)
  2202.     {
  2203.         diagonal(x0, y0, x1, y1, V.fontindex);    /* null line */
  2204.         return;
  2205.     }
  2206.  
  2207.     setlengths(V.fontindex, &V);
  2208.  
  2209.     if (abs(y1 - y0) > abs(x1 - x0))
  2210.     {            /* longer axis is used as base */
  2211.         V.useXaxis = false;
  2212.         V.a0 = y0;
  2213.         V.b0 = x0;
  2214.         V.a1 = y1;
  2215.         V.b1 = x1;
  2216.     }
  2217.     else
  2218.     {
  2219.         V.useXaxis = true;
  2220.         V.a0 = x0;
  2221.         V.b0 = y0;
  2222.         V.a1 = x1;
  2223.         V.b1 = y1;
  2224.     }
  2225.     /* the distance between a0 and a1 is now greater than that between b0 and b1. */
  2226.  
  2227.     /* redefine distances as integral units along axes */
  2228.     V.s = distance(float_(V.a0), float_(V.b0), float_(V.a1), float_(V.b1));
  2229.  
  2230.     switch (V.line_type)
  2231.     {
  2232.  
  2233.     case solid:
  2234.         /* blank case */
  2235.         break;
  2236.     case dotted:
  2237.         V.gap = project(V.Dotgap, &V);
  2238.         V.dot = project(V.Dotdot, &V);
  2239.         break;
  2240.     case dashed:
  2241.         V.gap = project(V.Dashgap, &V);
  2242.         V.dash = project(V.Dashdash, &V);
  2243.         break;
  2244.     case dotdash:
  2245.         V.gap = project(V.DDotgap, &V);
  2246.         V.dot = project(V.DDotdot, &V);
  2247.         V.dash = project(V.DDotdash, &V);
  2248.         break;
  2249.     }
  2250.  
  2251.     /*
  2252.      * ensure direction of line is from smaller to larger along the longer axis
  2253.      */
  2254.     if (V.a0 > V.a1)
  2255.     {
  2256.         V.J = V.a0;
  2257.         V.a0 = V.a1;
  2258.         V.a1 = V.J;
  2259.         V.J = V.b0;
  2260.         V.b0 = V.b1;
  2261.         V.b1 = V.J;
  2262.     }
  2263.  
  2264.     setframesize(&V);
  2265.  
  2266.     a1ma0 = V.a1 - V.a0;
  2267.  
  2268.     /* fit is the number of frames that fit in line */
  2269.     if (V.frame != 0)
  2270.         fit = float_(a1ma0) / float_(V.frame);
  2271.     else
  2272.         fit = 1.0;
  2273.  
  2274.     if (fit >= 1.0)
  2275.         T = (int32) floor(fit + 0.5);
  2276.     else
  2277.     {
  2278.         /* change frame elements (dot, dash, gap) since frame is too large */
  2279.         switch (V.line_type)
  2280.         {
  2281.  
  2282.         case dotted:
  2283.             V.gap += a1ma0 - V.frame;
  2284.             if (V.gap < V.dot)
  2285.                 return;    /* exit */
  2286.             setframesize(&V);
  2287.             break;
  2288.  
  2289.         case dashed:
  2290.         case dotdash:
  2291.             /* idea:decrease gap; if too small then shrink dash and refigure gap */
  2292.             if (V.frame - a1ma0 > V.gap / 2)
  2293.             {
  2294.                 V.dash = (int32) floor(V.dash * fit * 0.80 + 0.5);
  2295.                 V.gap = (int32) floor(V.gap * fit + 0.5);
  2296.                 setframesize(&V);
  2297.             }
  2298.             V.gap += a1ma0 - V.frame;
  2299.             if (V.line_type == dotdash)
  2300.                 V.gap /= 2;
  2301.             if (V.gap < V.dot)
  2302.                 return;    /* exit */
  2303.             setframesize(&V);
  2304.             break;
  2305.         }        /* case */
  2306.         T = 1;        /* NOW it will fit */
  2307.     }            /* else */
  2308.  
  2309.  
  2310.     switch (V.line_type)
  2311.     {
  2312.     case solid:
  2313.         if (V.useXaxis)
  2314.             diagonal(V.a0, V.b0, V.a1, V.b1, V.fontindex);
  2315.         else
  2316.             diagonal(V.b0, V.a0, V.b1, V.a1, V.fontindex);
  2317.         break;
  2318.     case dotted:        /* dotted lines begin and end on a dot */
  2319.         if (T * V.frame + V.dot == a1ma0)
  2320.             spread(dotted, 0, T, &V);
  2321.         else if (T * V.frame + V.dot > a1ma0)
  2322.         {
  2323.             /*
  2324.              * gap := gap - ((T*frame+dot)-a1ma0); {
  2325.              */
  2326.             spread(dotted, a1ma0 - T * V.frame - V.dot, T, &V);
  2327.  
  2328.             /*
  2329.              * spread(dotted, a1ma0 - (T-1)*frame - dot, T-1); {
  2330.              */
  2331.         }
  2332.         else
  2333.             spread(dotted, a1ma0 - T * V.frame - V.dot, T, &V);
  2334.         break;
  2335.     case dashed:
  2336.         /*
  2337.          * dashed lines begin and end on dash : the beginning and ending dashes are at least half the dash length
  2338.          * int32.
  2339.          */
  2340.         if (T * V.frame + V.dash == a1ma0)
  2341.             spread(dashed, 0, T, &V);
  2342.         else if (T * V.frame + V.dash > a1ma0)
  2343.             balance(dashed, T * V.frame + V.dash - a1ma0, T, &V);
  2344.         else
  2345.             spread(dashed, a1ma0 - T * V.frame - V.dash, T, &V);
  2346.         break;
  2347.     case dotdash:
  2348.         /*
  2349.          * if ending on a dash then beginning and ending dashes are half the dash length long - final dots are full
  2350.          * dot length
  2351.          */
  2352.         if (T * V.frame + V.dash == a1ma0)
  2353.             spread(dotdash, 0, T, &V);
  2354.         else if (T * V.frame + V.dash + V.gap + V.dot == a1ma0)
  2355.             spread(dotdash, 0, T, &V);
  2356.         else if (T * V.frame + V.dash > a1ma0)
  2357.             balance(dotdash, T * V.frame + V.dash - a1ma0, T, &V);
  2358.         else if (T * V.frame + V.dash + V.gap + V.dot > a1ma0)
  2359.             spread(dotdash, a1ma0 - T * V.frame - V.dash, T, &V);
  2360.         else
  2361.             spread(dotdash, a1ma0 - T * V.frame - V.dash - V.gap - V.dot, T, &V);
  2362.         break;
  2363.     }
  2364. }
  2365.  
  2366. void 
  2367. clampthickness(thic)
  2368.     VThickness     *thic;
  2369. {
  2370.     /*
  2371.      * #### this is just a simple clamp really should be something like: while not (thic in set_of_appropriate_thicknesses)
  2372.      * do modify thic and try again
  2373.      */
  2374.     if (*thic <= LoVThick)
  2375.         *thic = LoVThick + 1;
  2376.     while (((1 << (*thic)) & 0x1ffe) == 0 && *thic <= HiVThick)
  2377.         (*thic)++;
  2378.     if (*thic > HiVThick)
  2379.         *thic = HiVThick;
  2380. }
  2381.  
  2382. static void 
  2383. slurclamp(thic, totpts)
  2384.     VThickness     *thic;
  2385.     int32           totpts;
  2386. {
  2387.     /*
  2388.      * this post-clamps the sampled thicknesses calculated over the whole of the spline
  2389.      */
  2390.     int32           i, oneseventh, middle, startval, endval;
  2391.     double          deltaval, val, incrval, alpha, alphaincr;
  2392.  
  2393.     /*
  2394.      * $$ NOTE:: How does the ttspline interpolation of thicknesses compare to the below results?? Can we avoid having it
  2395.      * done elsewhere and concentrate on it here??
  2396.      */
  2397.  
  2398.     oneseventh = (int32) floor(totpts / 7.0 + 0.5);
  2399.     for (i = 1; i <= oneseventh; i++)
  2400.         thic[i] = thic[1];
  2401.     for (i = oneseventh * 6; i <= totpts; i++)
  2402.         thic[i] = thic[totpts];
  2403.  
  2404.     middle = (int32) floor(totpts / 2.0 + 0.5);
  2405.     for (i = oneseventh * 3; i <= oneseventh * 4; i++)
  2406.         thic[i] = thic[middle];
  2407.  
  2408.     startval = thic[oneseventh - 1];
  2409.     endval = thic[oneseventh * 3 + 1];
  2410.     deltaval = (endval - startval) * 2.0 / (oneseventh * 2);
  2411.     alphaincr = PI / (oneseventh * 2 + 1);
  2412.     alpha = PI;
  2413.     val = float_(startval);
  2414.     for (i = oneseventh; i < oneseventh * 3; i++)
  2415.     {            /* interpolate: ease in from minthick to middlethickness */
  2416.         alpha += alphaincr;
  2417.         incrval = (cos(alpha) + 1.0) / 2.0 * deltaval;
  2418.         val += incrval;
  2419.         thic[i] = (int32) floor(val + 0.5);
  2420.     }
  2421.  
  2422.     startval = thic[oneseventh * 4 - 1];
  2423.     endval = thic[oneseventh * 6 + 1];
  2424.     deltaval = (endval - startval) * 2.0 / (oneseventh * 2);
  2425.     alphaincr = PI / (oneseventh * 2 + 1);
  2426.     alpha = 0.0;
  2427.     val = float_(startval);
  2428.     for (i = oneseventh * 4 + 1; i <= oneseventh * 6; i++)
  2429.     {            /* ease out from middle thickness to min thick at far end */
  2430.         alpha += alphaincr;
  2431.         incrval = (cos(alpha) + 1.0) / 2.0 * deltaval;
  2432.         val += incrval;
  2433.         thic[i] = (int32) floor(val + 0.5);
  2434.     }
  2435. }
  2436.  
  2437. void 
  2438. layline(xl, yb, xr, yt, fontindex, pattern, useVecfontOnly)
  2439.     int32           xl, yb, xr, yt, fontindex;
  2440.     LineStyle       pattern;
  2441.     int        useVecfontOnly;
  2442. {
  2443.     int32           t;
  2444.  
  2445.     if (xr < xl)
  2446.     {
  2447.         t = xr;
  2448.         xr = xl;
  2449.         xl = t;
  2450.         t = yb;
  2451.         yb = yt;
  2452.         yt = t;
  2453.     }
  2454.  
  2455.     isetfont(VFontTable[fontindex - 1]->DVIFontNum);
  2456.  
  2457.     /*
  2458.      * we may want to require using a vector font only, instead of a combination of vectors and TeX-rules. It may look
  2459.      * better this way.
  2460.      */
  2461.     if (useVecfontOnly)
  2462.     {
  2463.         tylBrokenLine(xl, yb, xr, yt, fontindex, pattern);
  2464.         return;
  2465.     }
  2466.  
  2467.     if ((xl != xr || yb != yt) && (xl == xr || yb == yt))
  2468.     {            /* Null or diagonal lines */
  2469.         /*
  2470.          * if (pattern = solid) then hvline (xl, yb, xr, yt, fontindex) (* make use of rules *) else USENORULES
  2471.          */
  2472.         tylBrokenLine(xl, yb, xr, yt, fontindex, pattern);
  2473.         return;
  2474.     }
  2475.     if (pattern == solid)
  2476.         diagonal(xl, yb, xr, yt, fontindex);
  2477.     else
  2478.         tylBrokenLine(xl, yb, xr, yt, fontindex, pattern);
  2479.     /* be smart about the lines */
  2480. }
  2481.  
  2482.  
  2483. #define DontDoThicks    false
  2484. #define VectorsOnly     true
  2485.  
  2486. /* Local variables for layAspline: */
  2487. struct LOC_layAspline
  2488. {
  2489.     VThickness      thick;
  2490. };
  2491.  
  2492. void 
  2493. layAspline(thetype, isclosed, isanArc, domarks, cpts, numpts,
  2494.        thick_, vkind, patt)
  2495.     SplineKind      thetype;
  2496.     int        isclosed, isanArc;
  2497.     int32           domarks;
  2498. int32(*cpts)[2];
  2499.     int32           numpts;
  2500.     VThickness      thick_;
  2501.     VectKind        vkind;
  2502.     LineStyle       patt;
  2503. {
  2504.     struct LOC_layAspline V;
  2505.     SplineSegments  pointList;
  2506.     int32           i, xs, ys;
  2507.     ThickAryType    tt1, tt2;
  2508.     VecIndex        F;
  2509.     int32           FORLIM;
  2510.  
  2511.     V.thick = thick_;
  2512.     clampthickness(&V.thick);
  2513.     for (i = 0; i <= numpts + 3; i++)
  2514.         tt1[i] = V.thick;
  2515.  
  2516.     /* do any marks if necessary to show the control points */
  2517.     if (domarks > 0)
  2518.     {
  2519.         F = GetVectFont((int) domarks, VKCirc);
  2520.         isetfont(VFontTable[F - 1]->DVIFontNum);
  2521.         for (i = 1; i <= numpts; i++)
  2522.             Tyldot(cpts[i][0], cpts[i][1]);
  2523.     }
  2524.  
  2525.     drawSpline(thetype, isclosed, isanArc, patt, numpts, cpts, pointList,
  2526.            DontDoThicks, tt1, tt2);
  2527.  
  2528.  
  2529.     F = GetVectFont(V.thick, vkind);
  2530.     xs = pointList[0][0];
  2531.     ys = pointList[0][1];
  2532.  
  2533.     FORLIM = lastPoint;
  2534.     for (i = 1; i < FORLIM; i++)
  2535.     {
  2536.         layline(xs, ys, pointList[i][0], pointList[i][1], F, patt, VectorsOnly);
  2537.         xs = pointList[i][0];
  2538.         ys = pointList[i][1];
  2539.     }
  2540.     if (isclosed)        /* complete the motion */
  2541.         layline(pointList[lastPoint - 1][0], pointList[lastPoint - 1]
  2542.             [1], pointList[0][0], pointList[0][1], F, patt, VectorsOnly);
  2543. }
  2544.  
  2545. #define NotAnArc        false
  2546. #define DoThicksToo     true
  2547. #define VectorsOnly     true
  2548.  
  2549. void 
  2550. layNspline(thetype, isclosed, isitaslur, domarks, cpts, numpts,
  2551.        thickmatrix, vkind, patt)
  2552.     SplineKind      thetype;
  2553.     int        isclosed, isitaslur;
  2554.     int32           domarks;
  2555. int32(*cpts)[2];
  2556.     int32           numpts;
  2557.     VThickness     *thickmatrix;
  2558.     VectKind        vkind;
  2559.     LineStyle       patt;
  2560. {
  2561.     SplineSegments  pointList;
  2562.     int32           i, xs, ys;
  2563.     VThickness      ts;
  2564.     ThickAryType    tt;
  2565.     VecIndex        F;
  2566.     int32           FORLIM;
  2567.  
  2568.     /* do any marks if necessary to show the control points */
  2569.     if (domarks > 0)
  2570.     {
  2571.         F = GetVectFont((int) domarks, VKCirc);
  2572.         isetfont(VFontTable[F - 1]->DVIFontNum);
  2573.         for (i = 1; i <= numpts; i++)
  2574.             Tyldot(cpts[i][0], cpts[i][1]);
  2575.     }
  2576.  
  2577.     drawSpline(thetype, isclosed, NotAnArc, patt, numpts, cpts, pointList,
  2578.            DoThicksToo, thickmatrix, tt);
  2579.     if (isitaslur && !skiptsclamp)
  2580.         slurclamp(tt, lastPoint);    /* which kind of clamping to use */
  2581.  
  2582.     xs = pointList[0][0];
  2583.     ys = pointList[0][1];
  2584.     ts = tt[1];
  2585.  
  2586.     FORLIM = lastPoint;
  2587.     for (i = 1; i < FORLIM; i++)
  2588.     {
  2589.         clampthickness(&ts);
  2590.         F = GetVectFont(ts, vkind);
  2591.         layline(xs, ys, pointList[i][0], pointList[i][1], F, patt, VectorsOnly);
  2592.         xs = pointList[i][0];
  2593.         ys = pointList[i][1];
  2594.         ts = tt[i + 1];
  2595.     }
  2596.     if (!isclosed)
  2597.         return;
  2598.     ts = tt[lastPoint];
  2599.     clampthickness(&ts);
  2600.     F = GetVectFont(ts, vkind);
  2601.     layline(pointList[lastPoint - 1][0], pointList[lastPoint - 1]
  2602.         [1], pointList[0][0], pointList[0][1], F, patt, VectorsOnly);
  2603. }
  2604.  
  2605. /* && start dvidvi section */
  2606. /*-----------------------------------------------------*/
  2607. static void 
  2608. initialize()
  2609. {
  2610.     initVnMnLtables();
  2611.     multifigure = 0;
  2612.     pgfigurenum = 0;
  2613.     TotBytesWritten = 0;
  2614.     ourq = 0;
  2615.     currpagenum = 0;
  2616.     FTBDs = 0;
  2617.     InitDVIBuf();
  2618.     inpostamble = false;
  2619.     didnewfonts = false;
  2620.     skiptsclamp = false;
  2621.     ErrorOccurred = false;
  2622. }
  2623.  
  2624. /*-----------------------------------------------------*/
  2625. static int 
  2626. inTFM(z)
  2627.     int32           z;
  2628. {
  2629.     int32           k, lh, nw, alpha, beta, FORLIM;
  2630.     fontinfo    *WITH;
  2631.  
  2632.     readtfmword();
  2633.     lh = b2 * 256 + b3;
  2634.     readtfmword();
  2635.     font[nf].bc = b0 * 256 + b1;
  2636.     font[nf].ec = b2 * 256 + b3;
  2637.     if (font[nf].ec < font[nf].bc)
  2638.         font[nf].bc = font[nf].ec + 1;
  2639.     readtfmword();
  2640.     nw = b0 * 256 + b1;
  2641.     if (nw == 0 || nw > 256)
  2642.         return (false);
  2643.     for (k = 1; k <= lh + 3; k++)
  2644.     {
  2645.         if (feof(tfmfile))
  2646.             return (false);
  2647.         readtfmword();
  2648.         if (k == 4)
  2649.         {
  2650.             if (b0 < 128)
  2651.                 tfmchecksum = ((b0 * 256 + b1) * 256 + b2) * 256 + b3;
  2652.             else
  2653.                 tfmchecksum = (((b0 - 256) * 256 + b1) * 256 + b2) * 256 + b3;
  2654.         }
  2655.     }
  2656.  
  2657.     FORLIM = font[nf].ec - font[nf].bc;
  2658.     for (k = 0; k <= FORLIM; k++)
  2659.     {
  2660.         readtfmword();
  2661.         if (b0 > nw)
  2662.             return (false);
  2663.         font[nf].widths[k] = b0;
  2664.     }
  2665.     alpha = z * 16;
  2666.     beta = 16;
  2667.     while (z >= TWO23)
  2668.     {
  2669.         z /= 2;
  2670.         beta /= 2;
  2671.     }
  2672.     for (k = 0; k < nw; k++)
  2673.     {
  2674.         readtfmword();
  2675.         inwidth[k] = ((b3 * z / 256 + b2 * z) / 256 + b1 * z) / beta;
  2676.         if (b0 > 0)
  2677.         {
  2678.             if (b0 < 255)
  2679.                 return (false);
  2680.             inwidth[k] -= alpha;
  2681.         }
  2682.     }
  2683.     if (inwidth[0] != 0)
  2684.         return (false);
  2685.     WITH = &font[nf];    /* with */
  2686.     FORLIM = WITH->ec - WITH->bc;
  2687.     for (k = 0; k <= FORLIM; k++)
  2688.     {
  2689.         if (WITH->widths[k] == 0)
  2690.         {
  2691.             WITH->widths[k + WITH->bc] = TWO31;
  2692.             /* pixelwidths[k + bc] := 0; */
  2693.         }
  2694.         else
  2695.         {
  2696.             WITH->widths[k + WITH->bc] = inwidth[WITH->widths[k]];
  2697.             /* pixelwidths[k + bc] := round(conv * widths[k]); */
  2698.         }
  2699.     }
  2700.     return (true);
  2701. }
  2702.  
  2703. static void 
  2704. Fastdefinefont(fn)
  2705.     int32           fn;
  2706. {
  2707.     int32           p, k, n;
  2708.  
  2709.     (void) Dsign4byte();
  2710.     (void) Dsign4byte();
  2711.     (void) Dsign4byte();
  2712.     p = Dget1byte();
  2713.     n = Dget1byte();
  2714.     for (k = 1; k <= p + n; k++)
  2715.         (void) Dget1byte();
  2716. }                /* Fastdefinefont */
  2717.  
  2718. static void 
  2719. definefont(e)
  2720.     int32           e;
  2721. {
  2722.     char            f;
  2723.     int32           p, k, n, c, q, d;
  2724.     charstring      tfmname;
  2725.  
  2726.     if (nf == MAXFONTS)
  2727.     {
  2728.         complain(ERRREALBAD);
  2729.         fprintf(logfile, "TeXtyl capacity exceeded (max fonts=%d)!\n",
  2730.             MAXFONTS);
  2731.         jumpout();
  2732.     }
  2733.     font[nf].num = e;
  2734.     f = 0;
  2735.     while (font[f].num != e)/* find first occurrence */
  2736.         f++;
  2737.     c = Dsign4byte();
  2738.     font[nf].checksum = c;
  2739.     q = Dsign4byte();
  2740.     font[nf].scaledsize = q;
  2741.     d = Dsign4byte();
  2742.     font[nf].designsize = d;
  2743.     p = Dget1byte();
  2744.     n = Dget1byte();
  2745.     for (k = 0; k < p + n; k++)
  2746.         font[nf].name[k] = Dget1byte();
  2747.     font[nf].name[k] = '\0';
  2748.  
  2749.     if (f != nf)        /* f = nf */
  2750.         return;
  2751.  
  2752.     strcpy(tfmname, font[nf].name);
  2753.     strcat(tfmname, ".tfm");
  2754.  
  2755.     if (!opentfmfile(tfmname))
  2756.     {
  2757.         complain(ERRREALBAD);
  2758.         fprintf(logfile, "%s---not loaded, TFM file can't be opened!\n", tfmname);
  2759.         jumpout();
  2760.         return;
  2761.     }
  2762.     if (q <= 0 || q >= TWO27)
  2763.     {
  2764.         complain(ERRREALBAD);
  2765.         fprintf(logfile, "%s---not loaded, bad scale (%d)!\n", tfmname, q);
  2766.         return;
  2767.     }
  2768.     if (d <= 0 || d >= TWO27)
  2769.     {
  2770.         complain(ERRREALBAD);
  2771.         fprintf(logfile, "%s---not loaded, bad design size (%d)!\n", tfmname, d);
  2772.         return;
  2773.     }
  2774.     if (!inTFM(q))
  2775.     {            /* intfm */
  2776.         complain(ERRREALBAD);
  2777.         fprintf(logfile, "%s---not loaded, TFM file is bad\n", tfmname);
  2778.         return;
  2779.     }            /* intfm */
  2780.     font[nf].space = q / 6;
  2781.     if (c != 0 && tfmchecksum != 0 && c != tfmchecksum)
  2782.     {
  2783.         fprintf(logfile, "Problem in fig#%d on page %d\n",
  2784.             pgfigurenum, currpagenum);
  2785.         fprintf(logfile, "%s---beware: check sums do not agree!\n", tfmname);
  2786.         fprintf(logfile, "   (%d vs. %d)\n", c, tfmchecksum);
  2787.     }
  2788.     d = (int32) floor(100.0 * conv * q / (trueconv * d) + 0.5);
  2789.     nf++;
  2790.     font[nf].space = 0;
  2791. }
  2792.  
  2793. static int32 
  2794. firstpar(o)
  2795.     int             o;
  2796. {
  2797.     int32           fpar;
  2798.  
  2799.     if (0 <= o && o <= 127)
  2800.         fpar = o;
  2801.     else if (171 <= o && o <= 234)
  2802.         fpar = o - 171;
  2803.     else
  2804.         switch (o)
  2805.         {
  2806.         case 128:
  2807.         case 133:
  2808.         case 235:
  2809.         case 239:
  2810.         case 243:
  2811.             fpar = Dget1byte();
  2812.             break;
  2813.         case 129:
  2814.         case 134:
  2815.         case 236:
  2816.         case 240:
  2817.         case 244:
  2818.             fpar = Dget2byte();
  2819.             break;
  2820.         case 130:
  2821.         case 135:
  2822.         case 237:
  2823.         case 241:
  2824.         case 245:
  2825.             fpar = Dget3byte();
  2826.             break;
  2827.         case 143:
  2828.         case 148:
  2829.         case 153:
  2830.         case 157:
  2831.         case 162:
  2832.         case 167:
  2833.             fpar = Dsign1byte();
  2834.             break;
  2835.         case 144:
  2836.         case 149:
  2837.         case 154:
  2838.         case 158:
  2839.         case 163:
  2840.         case 168:
  2841.             fpar = Dsign2byte();
  2842.             break;
  2843.         case 145:
  2844.         case 150:
  2845.         case 155:
  2846.         case 159:
  2847.         case 164:
  2848.         case 169:
  2849.             fpar = Dsign3byte();
  2850.             break;
  2851.         case 131:
  2852.         case 132:
  2853.         case 136:
  2854.         case 137:
  2855.         case 146:
  2856.         case 151:
  2857.         case 156:
  2858.         case 160:
  2859.         case 165:
  2860.         case 170:
  2861.         case 238:
  2862.         case 242:
  2863.         case 246:
  2864.             fpar = Dsign4byte();
  2865.             break;
  2866.         case 138:
  2867.         case 139:
  2868.         case 140:
  2869.         case 141:
  2870.         case 142:
  2871.         case 247:
  2872.         case 248:
  2873.         case 249:
  2874.         case 250:
  2875.         case 251:
  2876.         case 252:
  2877.         case 253:
  2878.         case 254:
  2879.         case 255:
  2880.             fpar = 0;
  2881.             break;
  2882.         case 147:
  2883.             fpar = w;
  2884.             break;
  2885.         case 152:
  2886.             fpar = x;
  2887.             break;
  2888.         case 161:
  2889.             fpar = y;
  2890.             break;
  2891.         case 166:
  2892.             fpar = z;
  2893.             break;
  2894.         }
  2895.     return fpar;
  2896. }
  2897.  
  2898. static int 
  2899. specialcases(o, p)
  2900.     int32           o, p;
  2901. {
  2902.     if (o < 157 || o > 249)
  2903.     {
  2904.         complain(ERRREALBAD);
  2905.         fprintf(logfile, "undefined command %d!\n", o);
  2906.         return (true);
  2907.     }
  2908.     else if (171 <= o && o <= 238)
  2909.     {
  2910.         font[nf].num = p;
  2911.         curfont = 0;
  2912.         while (font[curfont].num != p)
  2913.             curfont++;
  2914.         return (true);
  2915.     }
  2916.     switch (o)
  2917.     {
  2918.     case 157:
  2919.     case 158:
  2920.     case 159:
  2921.     case 160:
  2922.         break;
  2923.     case 161:
  2924.     case 162:
  2925.     case 163:
  2926.     case 164:
  2927.     case 165:
  2928.         y = p;
  2929.         break;
  2930.     case 166:
  2931.     case 167:
  2932.     case 168:
  2933.     case 169:
  2934.     case 170:
  2935.         z = p;
  2936.         break;
  2937.     case 243:
  2938.     case 244:
  2939.     case 245:
  2940.     case 246:
  2941.         definefont(p);
  2942.         return (true);
  2943.     case 239:
  2944.     case 240:
  2945.     case 241:
  2946.     case 242:        /* =========specials============= */
  2947.         mainhandlespecials(o, p);
  2948.         return (true);
  2949.     case 247:
  2950.         complain(ERRREALBAD);
  2951.         fprintf(logfile, "preamble command within a page!\n");
  2952.         return (false);
  2953.     case 248:
  2954.     case 249:
  2955.         complain(ERRREALBAD);
  2956.         fprintf(logfile, "postamble command within a page!\n");
  2957.         return (false);
  2958.     }
  2959.     if (v > 0 && p > 0)
  2960.     {
  2961.         if (v > TWO31 - p)
  2962.             p = TWO31 - v;
  2963.     }
  2964.     if (v < 0 && p < 0)
  2965.     {
  2966.         if (-v > p + TWO31)
  2967.             p = -v - TWO31;
  2968.     }
  2969.     v += p;
  2970.     return (true);
  2971. }
  2972.  
  2973. static int 
  2974. dopage()
  2975. {
  2976.     int32           o, p, q;
  2977.     struct stackrec *WITH;
  2978.  
  2979.     curfont = nf;
  2980.     s = 0;
  2981.     h = 0;
  2982.     v = 0;
  2983.     w = 0;
  2984.     x = 0;
  2985.     y = 0;
  2986.     z = 0;
  2987.  
  2988.     ourxpos = 0;
  2989.     ourypos = 0;
  2990.     ourfontnum = -1;
  2991.     for (;;)
  2992.     {
  2993.         o = Dget1byte();
  2994.         p = firstpar(o);
  2995.         if (feof(dvifile))
  2996.         {
  2997.             fprintf(logfile, "Bad DVI file: the file ended prematurely!\n");
  2998.             jumpout();
  2999.         }
  3000.         if (o <= 131)
  3001.             goto _L41;
  3002.         if (o > 156)
  3003.         {
  3004.             if (specialcases(o, p))
  3005.                 continue;
  3006.             else
  3007.                 return (false);
  3008.         }
  3009.  
  3010.         switch (o)
  3011.         {
  3012.         case 133:
  3013.         case 134:
  3014.         case 135:
  3015.         case 136:
  3016.             goto _L41;
  3017.             break;
  3018.         case 132:
  3019.         case 137:
  3020.             goto _L42;
  3021.             break;
  3022.         case 138:
  3023.             continue;
  3024.         case 139:    /* BOP */
  3025.             complain(ERRREALBAD);
  3026.             fprintf(logfile, "bop occurred before eop\n");
  3027.             return (false);    /* Fail */
  3028.             break;
  3029.         case 140:    /* EOP */
  3030.             if (s != 0)
  3031.             {
  3032.                 complain(ERRREALBAD);
  3033.                 fprintf(logfile, "stack not empty at end of page (level %d)!\n", s);
  3034.             }
  3035.             if (multifigure != 0)
  3036.             {
  3037.                 complain(ERRBAD);
  3038.                 fprintf(logfile,
  3039.                     "Some figure definition not closed at end of page %d!\n",
  3040.                     currpagenum);
  3041.             }
  3042.             fprintf(logfile, "%d]", currpagenum);
  3043.             if (currpagenum % 10 == 0)
  3044.                 putc('\n', logfile);
  3045.             return (true);
  3046.         case 141:    /* PUSH */
  3047.             WITH = &stack[s];    /* with */
  3048.             WITH->sh = h;
  3049.             WITH->sv = v;
  3050.             WITH->sw = w;
  3051.             WITH->sx = x;
  3052.             WITH->sy = y;
  3053.             WITH->sz = z;
  3054.             s++;
  3055.             continue;
  3056.         case 142:    /* POP */
  3057.             if (s == 0)
  3058.             {
  3059.                 complain(ERRREALBAD);
  3060.                 fprintf(logfile, "illegal pop at level zero!\n");
  3061.             }
  3062.             else
  3063.             {
  3064.                 s--;
  3065.                 WITH = &stack[s];
  3066.                 h = WITH->sh;
  3067.                 v = WITH->sv;
  3068.                 w = WITH->sw;
  3069.                 x = WITH->sx;
  3070.                 y = WITH->sy;
  3071.                 z = WITH->sz;
  3072.             }
  3073.             continue;
  3074.         case 143:
  3075.         case 144:
  3076.         case 145:
  3077.         case 146:
  3078.             q = p;
  3079.             goto _L43;
  3080.             break;
  3081.         case 147:
  3082.         case 148:
  3083.         case 149:
  3084.         case 150:
  3085.         case 151:
  3086.             w = p;
  3087.             q = p;
  3088.             goto _L43;
  3089.             break;
  3090.         case 152:
  3091.         case 153:
  3092.         case 154:
  3093.         case 155:
  3094.         case 156:
  3095.             x = p;
  3096.             q = p;
  3097.             goto _L43;
  3098.             break;
  3099.         }        /* case */
  3100. _L41:                /* finish cmd to set/put a char */
  3101.         if (p < 0)
  3102.             p = 255 - ((-p - 1) & 255);
  3103.         else if (p >= 256)
  3104.             p &= 255;
  3105.         if (p < font[curfont].bc || p > font[curfont].ec)
  3106.             q = TWO31;
  3107.         else
  3108.             q = font[curfont].widths[p];
  3109.         if (q == TWO31)
  3110.         {
  3111.             complain(ERRREALBAD);
  3112.             fprintf(logfile, "Character %d invalid in font #%d\n", p, curfont);
  3113.         }
  3114.         if (o >= 133)
  3115.             continue;
  3116.         if (q == TWO31)
  3117.             q = 0;
  3118.         goto _L43;
  3119. _L42:                /* finish cmd to set/put rule */
  3120.         q = Dsign4byte();
  3121.         if (o == 137)
  3122.             continue;
  3123.         goto _L43;
  3124. _L43:                /* finish cmd that sets h += q */
  3125.         if (h > 0 && q > 0)
  3126.         {
  3127.             if (h > TWO31 - q)
  3128.                 q = TWO31 - h;
  3129.         }
  3130.         if (h < 0 && q < 0)
  3131.         {
  3132.             if (-h > q + TWO31)
  3133.                 q = -h - TWO31;
  3134.         }
  3135.         h += q;
  3136.     }
  3137. }
  3138.  
  3139. static void 
  3140. skippages()
  3141. {
  3142.     int32           p;
  3143.     int32           k;
  3144.  
  3145.     for (;;)
  3146.     {
  3147.         if (feof(dvifile))
  3148.         {
  3149.             fprintf(logfile, "Bad DVI file: the file ended prematurely!\n");
  3150.             jumpout();
  3151.         }
  3152.         k = Dget1byte();
  3153.         p = firstpar(k);
  3154.         switch (k)
  3155.         {
  3156.         case 139:    /* BOP */
  3157.             newbackptr = DVIMark() + TotBytesWritten - 1;
  3158.             currpagenum = Dsign4byte();    /* count[0] */
  3159.             for (k = 1; k <= 9; k++)    /* WAS count[k] := */
  3160.                 (void) Dsign4byte();
  3161.             (void) Dsign4byte();
  3162.             BackupInBuf(4);
  3163.             cmdSigned(oldbackptr, 4);
  3164.             oldbackptr = newbackptr;
  3165.             fprintf(logfile, "[");
  3166.             return;
  3167.         case 132:
  3168.         case 137:    /* RULE */
  3169.             (void) Dsign4byte();
  3170.             break;
  3171.         case 243:
  3172.         case 244:
  3173.         case 245:
  3174.         case 246:
  3175.             definefont(p);
  3176.             break;
  3177.         case 239:
  3178.         case 240:
  3179.         case 241:
  3180.         case 242:    /* specials */
  3181.             mainhandlespecials(k, p);
  3182.             break;
  3183.         case 248:    /* POST */
  3184.             ourq = DVIMark() + TotBytesWritten - 1;
  3185.             inpostamble = true;
  3186.             return;
  3187.         }
  3188.     }
  3189. }
  3190.  
  3191. static void 
  3192. readpostamble()
  3193. {
  3194.     int32           k, p, m, indx, FORLIM;
  3195.     MusFontInfRec  *WITH;
  3196.     VectFontInfRec *WITH1;
  3197.     LabFontInfRec  *WITH2;
  3198.  
  3199.     if (Dsign4byte() != numerator)
  3200.         fprintf(logfile, "Postamble numerator doesn't match the preamble!\n");
  3201.     if (Dsign4byte() != denominator)
  3202.         fprintf(logfile, "Postamble denominator doesn't match the preamble!\n");
  3203.     if (Dsign4byte() != mag)
  3204.         fprintf(logfile, "Postamble magnification doesn't match the preamble!\n");
  3205.     maxv = Dsign4byte();
  3206.     maxh = Dsign4byte();
  3207.     maxs = Dget2byte();
  3208.     BackupInBuf(2);
  3209.     cmd2byte(maxs + 2);
  3210.     /*
  3211.      * pretend the stack depth does not increase by more than two
  3212.      */
  3213.     totalpages = Dget2byte();
  3214.     do
  3215.     {
  3216.         k = Dget1byte();
  3217.         if (k >= 243 && k < 247)
  3218.         {
  3219.             p = firstpar(k);
  3220.             Fastdefinefont(p);
  3221.             k = 138;
  3222.         }
  3223.     } while (k == 138);    /* NOP */
  3224.  
  3225.     /*
  3226.      * here, backup 1, enter all our fonts and then output the 249 that we backed over
  3227.      */
  3228.     BackupInBuf(1);
  3229.     FORLIM = MFontsDefd;
  3230.     for (indx = 0; indx < FORLIM; indx++)
  3231.     {
  3232.         WITH = MFontTable[indx];
  3233.         enterfont(WITH->DVIFontNum, WITH->Cksum, WITH->DesSize, WITH->DesSize,
  3234.               WITH->FontName);
  3235.     }            /* for */
  3236.     FORLIM = VFontsDefd;
  3237.     for (indx = 0; indx < FORLIM; indx++)
  3238.     {
  3239.         WITH1 = VFontTable[indx];
  3240.         enterfont(WITH1->DVIFontNum, WITH1->Cksum, WITH1->DesSize, WITH1->DesSize,
  3241.               WITH1->FontName);
  3242.     }            /* for */
  3243.     FORLIM = LFontsDefd;
  3244.     for (indx = 0; indx < FORLIM; indx++)
  3245.     {
  3246.         WITH2 = LFontTable[indx];
  3247.         enterfont(WITH2->DVIFontNum, WITH2->Cksum, WITH2->DesSize, WITH2->DesSize,
  3248.               WITH2->FontName);
  3249.     }
  3250.     cmd1byte(249);        /* post post */
  3251.  
  3252.     if (k != 249)
  3253.         fprintf(logfile, "byte %d is not postpost!\n", k);
  3254.     (void) Dsign4byte();
  3255.     BackupInBuf(4);
  3256.     cmd4byte(ourq);
  3257.     m = Dget1byte();
  3258.     if (m != 2)
  3259.         fprintf(logfile, "identification should be %d!\n", 2);
  3260.     m = 223;
  3261.     while ((m == 223) && (!feof(dvifile)))
  3262.         m = Dget1byte();
  3263.     if (feof(dvifile))
  3264.         return;
  3265.     fprintf(logfile, "Bad DVI file: signature in should be 223!\n");
  3266.     jumpout();
  3267. }
  3268.  
  3269.  
  3270. /* MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN MAIN */
  3271. int
  3272. main(argc, argv)
  3273.     int             argc;
  3274.     char           *argv[];
  3275. {
  3276.     void        exit PP((int));
  3277.  
  3278.     if (setjmp(_JL666))
  3279.         goto _L666;
  3280.     initialize();
  3281.     if (argc < 3)
  3282.     {
  3283.         fprintf(stderr, "Usage: textyl dvi-in dvi-out\n");
  3284.         exit(1);
  3285.     }
  3286.     if ((dvifile = fopen(argv[1], "r")) == NULL)
  3287.     {
  3288.         perror(argv[1]);
  3289.         exit(1);
  3290.     }
  3291.     if ((outputfil = fopen(argv[2], "w")) == NULL)
  3292.     {
  3293.         perror(argv[2]);
  3294.         exit(1);
  3295.     }
  3296.     logfile = stdout;
  3297.     fprintf(logfile, "%s for Berkeley Unix\n", TylVersion);
  3298.  
  3299.     p = Dget1byte();
  3300.     if (p != 247)
  3301.     {
  3302.         fprintf(logfile, "Bad DVI file: First byte isn't start of preamble!!\n");
  3303.         jumpout();
  3304.     }
  3305.     p = Dget1byte();
  3306.     if (p != 2)
  3307.         fprintf(logfile, "identification in byte 1 should be %d!\n", 2);
  3308.     numerator = Dsign4byte();
  3309.     denominator = Dsign4byte();
  3310.     if (numerator <= 0)
  3311.     {
  3312.         fprintf(logfile, "Bad DVI file: numerator is %d!\n", numerator);
  3313.         jumpout();
  3314.     }
  3315.     if (denominator <= 0)
  3316.     {
  3317.         fprintf(logfile, "Bad DVI file: denominator is %d!\n", denominator);
  3318.         jumpout();
  3319.     }
  3320.     conv = numerator / 254000.0 * (resolution / denominator);
  3321.     mag = Dsign4byte();
  3322.     if (mag <= 0)
  3323.     {
  3324.         fprintf(logfile, "Bad DVI file: magnification is % .1E!\n", mag);
  3325.         jumpout();
  3326.     }
  3327.     magfactor = mag / 1000.0;
  3328.     trueconv = conv;
  3329.     conv = trueconv * magfactor;
  3330.     p = Dget1byte();    /* the 'k' of the preamble */
  3331.     while (p > 0)
  3332.     {
  3333.         p--;
  3334.         (void) Dget1byte();
  3335.     }
  3336.  
  3337.     skippages();
  3338.     if (!inpostamble)
  3339.     {
  3340.         while (maxpages-- > 0)
  3341.         {        /* while */
  3342.             if (!dopage())
  3343.             {
  3344.                 printf(" Bad DVI file: page ended unexpectedly!");
  3345.                 fprintf(logfile, "Bad DVI file: page ended unexpectedly!\n");
  3346.                 jumpout();
  3347.             }
  3348.             WriteDVIBuf();
  3349.             ClearDVIBuf();
  3350.             multifigure = 0;
  3351.             pgfigurenum = 0;
  3352.             FTBDs = 0;
  3353.             didnewfonts = false;
  3354.             do
  3355.             {
  3356.                 k = Dget1byte();
  3357.                 if (k >= 243 && k < 247)
  3358.                 {    /* fontdefs */
  3359.                     p = firstpar(k);
  3360.                     definefont(p);
  3361.                     k = 138;
  3362.                 }
  3363.             } while (k == 138);    /* nop */
  3364.  
  3365.             if (k == 248)
  3366.             {
  3367.                 inpostamble = true;
  3368.                 ourq = DVIMark() + TotBytesWritten - 1;
  3369.                 break;
  3370.             }
  3371.  
  3372.             if (k != 139)
  3373.             {    /* BOP */
  3374.                 fprintf(logfile, "We did not find BOP when expected\n");
  3375.                 jumpout();
  3376.                 continue;
  3377.             }
  3378.  
  3379.             newbackptr = DVIMark() + TotBytesWritten - 1;
  3380.             currpagenum = Dsign4byte();    /* Count[0] */
  3381.             for (k = 1; k <= 9; k++)    /* WAS count[k] := */
  3382.                 (void) Dsign4byte();
  3383.             (void) Dsign4byte();    /* backpointer */
  3384.             BackupInBuf(4);
  3385.             cmdSigned(oldbackptr, 4);
  3386.             oldbackptr = newbackptr;
  3387.             fprintf(logfile, "[");
  3388.         }        /* while */
  3389.     }            /* if not inpostamble */
  3390.     if (!inpostamble)
  3391.         skippages();
  3392.     (void) Dsign4byte();    /* ptr to the last bop in file */
  3393.     BackupInBuf(4);
  3394.     cmdSigned(oldbackptr, 4);
  3395.     readpostamble();
  3396.     WriteDVIBuf();
  3397.  
  3398.     while ((TotBytesWritten & 3) != 0)    /* final signatures */
  3399.         OutputByte(223);
  3400.  
  3401.     fprintf(logfile, "(%d page", currpagenum);
  3402.     if (currpagenum > 1)
  3403.         putc('s', logfile);
  3404.     fprintf(logfile, ", %d bytes).\n", TotBytesWritten);
  3405.  
  3406. _L666:
  3407.     if (ErrorOccurred)
  3408.     {
  3409.         fprintf(logfile, "\nSome error(s) occurred.\n");
  3410.         fprintf(logfile, "Assume that the outputfile is incorrect\n");
  3411.     }
  3412.     if (dvifile != NULL)
  3413.         fclose(dvifile);
  3414.     if (tfmfile != NULL)
  3415.         fclose(tfmfile);
  3416.     if (outputfil != NULL)
  3417.         fclose(outputfil);
  3418.     if (logfile != NULL)
  3419.         fclose(logfile);
  3420.     exit(0);
  3421.     return (0);
  3422. }
  3423.